题解:P14438 [JOISC 2013] 切割蛋糕 / Cake
_determination_ · · 题解
首先你要断环为链。考虑最小值,你显然不会越过这个位置。故将最小值旋转至
考虑建出
对于子树内:设
这样定义有一些好处:
- 根据单调栈理论,
\sum m_i 是O(n) 的。 - 注意到
(L_{x+1,i},L_{x,i}) 处的值均大于a_{L_{x,i}} ,故取了L_{x,i} 后就会连续取这一段。也就是说我们可以花费O(n) 的时间来处理子树内的贡献。
一些细节是
然后就要考虑子树外:在取完
记
提交记录。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int mod=998244353,inf=0x3f3f3f3f3f3f3f3f;
const int N=3e5+10,M=2e5+10;
mt19937 rnd(time(0));
int n,a[N],Pos=1,ans[N];
vector<int>L[N],R[N];
int s[N][2];
inline int query(int l,int r,int op){return s[r][op]-s[l-1][op];}
int stk[N],top;
int f[N][2],g[N];
int ls[N],rs[N];
void dfs(int x,int l,int r)
{
ans[x]=g[x]+f[x][(r-l+1)&1];
if(ls[x])
{
f[ls[x]][0]=query(x,r,x&1)+f[x][(r-x+1)&1];
f[ls[x]][1]=query(x,r,(x&1)^1)+f[x][((r-x+1)&1)^1];
dfs(ls[x],l,x-1);
}
if(rs[x])
{
f[rs[x]][0]=query(l,x,x&1)+f[x][(x-l+1)&1];
f[rs[x]][1]=query(l,x,(x&1)^1)+f[x][((x-l+1)&1)^1];
dfs(rs[x],x+1,r);
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin >> n;
for ( int i = 1 ; i <= n ; i++ )cin >> a[i];
for ( int i = 2 ; i <= n ; i++ )if(a[Pos]>a[i])Pos=i;
rotate(a+1,a+Pos+1,a+1+n);
for ( int i = 1 ; i <= n ; i++ )s[i][i&1]=a[i];
for ( int i = 1 ; i <= n ; i++ )s[i][0]+=s[i-1][0],s[i][1]+=s[i-1][1];
{//solve(n)
int l=1,r=n-1,op=0;
ans[n]=a[n];
while(l<=r)
{
if(a[l]>a[r])
{
if(op)ans[n]+=a[l];
l++;
}else{
if(op)ans[n]+=a[r];
r--;
}
op^=1;
}
}
int root=0;
for ( int i = 1 ; i < n ; i++ )
{
while(a[stk[top]]>a[i])L[i].push_back(stk[top--]);
L[i].push_back(stk[top]);stk[++top]=i;
}
stk[top=0]=n;
for ( int i = n-1 ; i ; i-- )
{
while(a[stk[top]]>a[i])R[i].push_back(stk[top--]);
R[i].push_back(stk[top]);stk[++top]=i;
}
for ( int i = 1 ; i < n ; i++ )
{
g[i]=a[i];if(n&1)g[i]+=a[n];
int pl=0,pr=0,op=1;
while(pl+1<L[i].size()||pr+1<R[i].size())
{
if(a[L[i][pl]]>a[R[i][pr]])//这里可以直接如此而保证不越界,原因是 a[L[i].bk()],a[R[i].bk()] 都小于 a[i],导致对应分支进不去
{
g[i]+=query(L[i][pl+1]+1,L[i][pl],(L[i][pl]&1)^op);
op^=(L[i][pl]-L[i][pl+1])&1;pl++;
}else{
g[i]+=query(R[i][pr],R[i][pr+1]-1,(R[i][pr]&1)^op);
op^=(R[i][pr+1]-R[i][pr])&1;pr++;
}
}
if(a[L[i].back()]>a[R[i].back()])rs[L[i].back()]=i;
else if(R[i].back()==n)root=i;
else ls[R[i].back()]=i;
}
dfs(root,1,n-1);
rotate(ans+1,ans+n+1-Pos,ans+1+n);
for ( int i = 1 ; i <= n ; i++ )cout << ans[i] << endl;
return 0;
}