【IOI2014】bzoj4367 holiday
2017-07-05 22:00
211 查看
最优方案一定是先向一边走,然后掉头回来,再向另一边走停在最远处,剩下的时间取走一路上的最大值。
我们用f[0/1][0/1][i]表示用掉时间i,向左或向右,回到出发点或不回到,得到的最大收益。不难发现,这四个值求法类似。
如果知道到达的最远点的话,能取走的位置的个数是确定的。我么可以用主席树查询区间k大值和来O(logn)求出答案。而显然决策点是单调的,也就是说,时间越长,走到的最远点越远。于是我们可以分治求解,定义solve(L,R,l,r)表示求解[L,R]的f值,决策点在[l,r]。令mid=(L+R)/2,先暴力枚举决策点求出mid的最优决策x,这一步是O(nlogn)的,于是递归下去的时候决策点也分成了两部分。分治结构总共有O(logn)层,每一层求解的复杂度之和是O(nlogn),所以最后的复杂度是O(nlog2n)。
注意起点位置是不能被两边同时取走的,因此需要特殊处理。好像只有规定往回走的那一边取走起点才是对的,我也不知道为什么。
我们用f[0/1][0/1][i]表示用掉时间i,向左或向右,回到出发点或不回到,得到的最大收益。不难发现,这四个值求法类似。
如果知道到达的最远点的话,能取走的位置的个数是确定的。我么可以用主席树查询区间k大值和来O(logn)求出答案。而显然决策点是单调的,也就是说,时间越长,走到的最远点越远。于是我们可以分治求解,定义solve(L,R,l,r)表示求解[L,R]的f值,决策点在[l,r]。令mid=(L+R)/2,先暴力枚举决策点求出mid的最优决策x,这一步是O(nlogn)的,于是递归下去的时候决策点也分成了两部分。分治结构总共有O(logn)层,每一层求解的复杂度之和是O(nlogn),所以最后的复杂度是O(nlog2n)。
注意起点位置是不能被两边同时取走的,因此需要特殊处理。好像只有规定往回走的那一边取走起点才是对的,我也不知道为什么。
#include<cstdio> #include<algorithm> using namespace std; const int maxn=100010,maxt=2800000; #define LL long long int rd() { int x=0; char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x; } int a[maxn],val[maxn],size[maxt],lson[maxt],rson[maxt],rt[maxn],n,s,m,l,tot; LL sum[maxt],f[2][2][250010]; void build(int &u,int bro,int L,int R,int x) { u=++tot; size[u]=size[bro]+1; sum[u]=sum[bro]+val[x]; if (L==R) return; int mid=(L+R)/2; if (x<=mid) { build(lson[u],lson[bro],L,mid,x); rson[u]=rson[bro]; } else { lson[u]=lson[bro]; build(rson[u],rson[bro],mid+1,R,x); } } LL qry(int u,int v,int L,int R,int k) { if (k>=size[u]-size[v]) return sum[u]-sum[v]; if (L==R) return k*val[L]; int mid=(L+R)/2; if (k<=size[rson[u]]-size[rson[v]]) return qry(rson[u],rson[v],mid+1,R,k); return sum[rson[u]]-sum[rson[v]]+qry(lson[u],lson[v],L,mid,k-(size[rson[u]]-size[rson[v]])); } LL cal(int f1,int f2,int t,int p) { int u,v,x; if (f1) u=s+f2,v=p; else u=p,v=s-f2; x=t-abs(p-s)*(f2?1:2); if (x<=0||u>v) return 0; return qry(rt[v],rt[u-1],1,l,x); } void solve(int f1,int f2,int L,int R,int l,int r) { if (L>R) return; int mid=(L+R)/2,p=l; LL x; f[f1][f2][mid]=cal(f1,f2,mid,l); for (int i=l+1;i<=r;i++) { x=cal(f1,f2,mid,i); if (x>f[f1][f2][mid]) { p=i; f[f1][f2][mid]=x; } } if (f1) { solve(f1,f2,L,mid-1,l,p); solve(f1,f2,mid+1,R,p,r); } else { solve(f1,f2,L,mid-1,p,r); solve(f1,f2,mid+1,R,l,p); } } int main() { //freopen("f.in","r",stdin); //freopen("f.out","w",stdout); LL ans=0; n=rd(); s=rd()+1; m=rd(); for (int i=1;i<=n;i++) a[i]=val[i]=rd(); sort(val+1,val+n+1); l=unique(val+1,val+n+1)-val-1; for (int i=1;i<=n;i++) { a[i]=lower_bound(val+1,val+l+1,a[i])-val; build(rt[i],rt[i-1],1,l,a[i]); } solve(0,0,0,m,1,s); solve(0,1,0,m,1,s); solve(1,0,0,m,s,n); solve(1,1,0,m,s,n); for (int i=0;i<=m;i++) { ans=max(ans,f[0][0][i]+f[1][1][m-i]); ans=max(ans,f[0][1][i]+f[1][0][m-i]); } printf("%lld\n",ans); }
相关文章推荐
- [BZOJ4367][IOI2014]Holiday(决策单调性+分治+主席树)
- BZOJ 4367 [IOI2014]holiday假期 分治 主席树
- [bzoj4367][IOI2014]holiday假期
- [决策单调性 分治 主席树] BZOJ 4367 [IOI2014]holiday假期
- BZOJ4367 IOI2014holiday假期(整体二分+主席树)
- 【BZOJ4367】[IOI2014]holiday假期 分治+主席树
- 【IOI2014】【BZOJ4367】holiday假期
- bzoj5053 [ioi2014]Phidias 菲迪亚斯神
- IOI2014 day2 task4 Holiday
- uoj#29. 【IOI2014】Holiday
- IOI2014 假期(Holiday)
- bzoj 4364: [IOI2014]wall砖墙
- 【UOJ #29】【IOI 2014】holiday
- bzoj 4364: [IOI2014]wall砖墙 线段树
- [BZOJ]4364: [IOI2014]wall砖墙 线段树
- bzoj 4364: [IOI2014]wall砖墙
- BZOJ 3834 Poi2014 Solar Panels 数论
- bzoj3594 [Scoi2014]方伯伯的玉米田
- BZOJ 3434 Wc2014 时空穿梭 莫比乌斯反演
- [BZOJ3504][CQOI2014]危桥