BZOJ 4367 [IOI2014]holiday假期 分治 主席树
2016-05-13 18:34
351 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4367
题目大意:
有n个标号0到n−1的城市,从标号为start的城市出发旅行d天
每天可以选择参观所在城市的景点或者移动到相邻城市,求最多可以看多少景点
题解:
不难看出,若想尽可能看更多的景点,改变旅行方向的次数至多为1
可以分别预处理出: ①只向左走②只向右走③向左走并返回④向右走并返回 能参观的最大景点数
将它们拼接起来取最大值就能得到最终的答案了
处理出他们的方法极为类似,现在只研究如何求出只向右走能参观的最大景点数
用a[i]表示只向右走i天能参观到的最大景点数
我们可以枚举走到了城市x,那么我们就可以参观start到x这段区间中的i−x+start个城市的景点
显然我们要参观景点数最多的i−x+start个城市,用主席树可以轻松求出其中共有多少个景点
最后从所有st≤x≤n−1得到的答案中取最大值即可,但是时间复杂度O(n2log2n)难以接受
观察发现对于旅行天数的增加,取最优值得决策点不会向左移动
于是我们可以分治解决问题,每一次在决策范围内枚举得出a[mid]与决策点的位置,时间复杂度为O(nlog22n)
最后,不离散化MLE(╯°□°)╯︵┻━┻
代码:
题目大意:
有n个标号0到n−1的城市,从标号为start的城市出发旅行d天
每天可以选择参观所在城市的景点或者移动到相邻城市,求最多可以看多少景点
题解:
不难看出,若想尽可能看更多的景点,改变旅行方向的次数至多为1
可以分别预处理出: ①只向左走②只向右走③向左走并返回④向右走并返回 能参观的最大景点数
将它们拼接起来取最大值就能得到最终的答案了
处理出他们的方法极为类似,现在只研究如何求出只向右走能参观的最大景点数
用a[i]表示只向右走i天能参观到的最大景点数
我们可以枚举走到了城市x,那么我们就可以参观start到x这段区间中的i−x+start个城市的景点
显然我们要参观景点数最多的i−x+start个城市,用主席树可以轻松求出其中共有多少个景点
最后从所有st≤x≤n−1得到的答案中取最大值即可,但是时间复杂度O(n2log2n)难以接受
观察发现对于旅行天数的增加,取最优值得决策点不会向左移动
于是我们可以分治解决问题,每一次在决策范围内枚举得出a[mid]与决策点的位置,时间复杂度为O(nlog22n)
最后,不离散化MLE(╯°□°)╯︵┻━┻
代码:
#include <bits/stdc++.h> using namespace std; #define MAXN 100005 typedef long long ll; int n,st,D; int aa[MAXN]; pair<int,int*>bb[MAXN]; int tt; int cc[MAXN]; struct Node { int num; ll sum; int l,r; }tr[MAXN*20]; int root[MAXN],tot; void Update(int val,int l,int r,int &rt) { tr[++tot]=tr[rt];rt=tot; tr[rt].num++; tr[rt].sum+=cc[val]; if(l==r) return; int mid=(l+r)>>1; if(val<=mid) Update(val,l,mid,tr[rt].l); else Update(val,mid+1,r,tr[rt].r); } ll Query(int k,int l,int r,int L,int R) { if(k<=0) return 0; if(tr[R].num-tr[L].num<=k) return tr[R].sum-tr[L].sum; if(l==r) return (tr[R].sum-tr[L].sum)/(tr[R].num-tr[L].num)*k; int mid=(l+r)>>1; if(tr[tr[R].r].num-tr[tr[L].r].num>=k) return Query(k,mid+1,r,tr[L].r,tr[R].r); else return tr[tr[R].r].sum-tr[tr[L].r].sum+Query(k-tr[tr[R].r].num+tr[tr[L].r].num,l,mid,tr[L].l,tr[R].l); } ll a[MAXN*2],b[MAXN*2],c[MAXN*3],d[MAXN*3]; void Geta(int l,int r,int L,int R) { if(l>r) return; int mid=(l+r)>>1; int w=L;a[mid]=Query(mid-L+st,1,tt,root[st-1],root[L]); for(int i=L+1;i<=R;i++) { ll tmp=Query(mid-i+st,1,tt,root[st-1],root[i]); if(tmp>a[mid]) a[mid]=tmp,w=i; } Geta(l,mid-1,L,w);Geta(mid+1,r,w,R); } void Getb(int l,int r,int L,int R) { if(l>r) return; int mid=(l+r)>>1; int w=R;b[mid]=Query(mid-st+R,1,tt,root[R-1],root[st]); for(int i=R-1;i>=L;i--) { ll tmp=Query(mid-st+i,1,tt,root[i-1],root[st]); if(tmp>b[mid]) b[mid]=tmp,w=i; } Getb(l,mid-1,w,R);Getb(mid+1,r,L,w); } void Getc(int l,int r,int L,int R) { if(l>r) return; int mid=(l+r)>>1; int w=R;c[mid]=Query(mid-st-st+R+R+1,1,tt,root[R-1],root[st-1]); for(int i=R-1;i>=L;i--) { ll tmp=Query(mid-st-st+i+i+1,1,tt,root[i-1],root[st-1]); if(tmp>c[mid]) c[mid]=tmp,w=i; } Getc(l,mid-1,w,R);Getc(mid+1,r,L,w); } void Getd(int l,int r,int L,int R) { if(l>r) return; int mid=(l+r)>>1; int w=L;d[mid]=Query(mid-L-L+st+st+1,1,tt,root[st],root[L]); for(int i=L+1;i<=R;i++) { ll tmp=Query(mid-i-i+st+st+1,1,tt,root[st],root[i]); if(tmp>d[mid]) d[mid]=tmp,w=i; } Getd(l,mid-1,L,w);Getd(mid+1,r,w,R); } int main() { scanf("%d%d%d",&n,&st,&D); for(int i=0;i<n;i++)scanf("%d",aa+i),bb[i]=make_pair(aa[i],aa+i); sort(bb,bb+n); for(int i=0;i<n;i++) { if(!i||bb[i].first!=bb[i-1].first) cc[++tt]=bb[i].first; *bb[i].second=tt; } for(int i=0;i<n;i++) { if(i) root[i]=root[i-1]; Update(aa[i],1,tt,root[i]); } Geta(0,n*2,st,n-1); Getb(0,n*2,0,st); if(st>0) Getc(0,n*3,0,st-1); if(st<n-1) Getd(0,n*3,st+1,n-1); ll ans=max(a[min(n*2,D)],b[min(n*2,D)]); for(int i=0;i<=n*2&&i<D-1;i++) { ans=max(ans,a[i]+c[D-i-1]); ans=max(ans,b[i]+d[D-i-1]); } printf("%lld\n",ans); return 0; }
相关文章推荐
- 对分治算法的几点思考
- BZOJ3275 Number (最小割)
- 关于“2”这个数字
- hdu 1007 -- Quoit Design
- [Leetcode题解]004 Median of Two Sorted Arrays
- 分治法求最大连续和
- Codeforces Round #299
- poj2299 分治
- [bzoj1003] [ZJOI2006]物流运输trans
- [bzoj1500][NOI2005]维修数列
- [bzoj1208] [HNOI2004]宠物收养所
- [bzoj1269][AHOI2006]文本编辑器editort
- [bzoj1503][NOI2004]郁闷的出纳员
- bzoj4305 数学
- bzoj3926 广义后缀自动机
- bzoj2780 广义后缀自动机+parent树+Dfs序+树状数组
- BZOJ1997 2-sat
- bzoj4027 贪心
- [BZOJ2038][2009国家集训队][莫队][分块]小z的袜子
- [BZOJ2594][WC2006][LCT][MST]水管局长数据加强版