【bzoj2388】【旅行规划】【分块+凸包】
来源:互联网 发布:网络直播平台赚钱吗 编辑:程序博客网 时间:2024/04/27 11:45
Description
OIVillage是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl决定修建了一条铁路将当地n个最著名的经典连接起来,让游客可以通过火车从铁路起点(1号景点)出发,依次游览每个景区。为了更好的评价这条铁路,xkszltl为每一个景区都哦赋予了一个美观度,而一条旅行路径的价值就是它所经过的景区的美观度之和。不过,随着天气与季节的变化,某些景点的美观度也会发生变化。
xkszltl希望为每位旅客提供最佳的旅行指导,但是由于游客的时间有限,不一定能游览全部景区,然而他们也不希望旅途过于短暂,所以每个游客都希望能在某一个区间内的车站结束旅程,而xkszltl的任务就是为他们选择一个终点使得旅行线路的价值最大。可是当地的景点与前来观光的旅客实在是太多了,xkszltl无法及时完成任务,于是找到了准备虐杀NOI2011的你,希望你能帮助他完成这个艰巨的任务。
Input
第一行给出一个整数n,接下来一行给出n的景区的初始美观度。
第三行给出一个整数m,接下来m行每行为一条指令:
1. 0 x y k:表示将x到y这段铁路边上的景区的美观度加上k;
2. 1 x y:表示有一名旅客想要在x到y这段(含x与y)中的某一站下车,你需要告诉他最大的旅行价值。
Output
对于每个询问,输出一个整数表示最大的旅行价值。
Sample Input
5
1 8 -8 3 -7
3
1 1 5
0 1 3 6
1 2 4
1 8 -8 3 -7
3
1 1 5
0 1 3 6
1 2 4
Sample Output
9
22
22
HINT
Data Limit:
对于20%的数据,n,m≤3000;
对于40%的数据,n,m≤30000;
对于50%的数据,n,m≤50000;
另外20%的数据,n,m≤100000,修改操作≤20;
对于100%的数据,n,m≤100000。
题解:
设s[i]为i位置美观度的前缀和.
把(i,s[i])看成一个点,考虑分块.
对于每一块,维护一个上凸壳,对于整块的询问就可以在凸壳上二分.
修改的时候可以发现是加一个等差数列,所以对于整块的可以直接打标记.
边缘的部分暴力修改然后暴力重构凸壳.
对于每次修改的右端点之后的块,等于是整块加一个值,
这样最优值的位置是不变的,所以直接打标记即可.
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define N 100010#define M 400#define ll long long#define inf 1LL<<60 using namespace std;int bk,n,m,cnt,kind,x,y,bl[N],l[M],r[M],st[N],xu[M][M],size[M];ll s[N],f[M],d[M],c[M],k,temp;int read(){ int x(0),f(1);char ch=getchar(); while (ch<'0'||ch>'9') { if (ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f;}void getbk(){ bk=sqrt(n); if (n%bk) cnt=n/bk+1; else cnt=n/bk; for (int i=1;i<=n;i++) bl[i]=(i-1)/bk+1; for (int i=1;i<=cnt;i++){ l[i]=(i-1)*bk+1; r[i]=min(n,bk*i); }}double cal(int x,int y){ return (double)(s[y]-s[x])/(double)(y-x); } void build(int x){ int top=0; st[++top]=l[x]; for (int i=l[x]+1;i<=r[x];i++){ while (top>1&&cal(st[top-1],st[top])<cal(st[top-1],i)) top--; st[++top]=i; } st[0]=0;st[top+1]=n+1;size[x]=top; for (int i=0;i<=top+1;i++) xu[x][i]=st[i];}void pushdown(int x){ temp=f[x]; for (int i=l[x];i<=r[x];i++){ s[i]+=temp;temp+=d[x];s[i]+=c[x]; } f[x]=c[x]=d[x]=0; }void change(int x,int y,ll k){ int a=bl[x],b=bl[y]; temp=k*(l[a+1]-x+1); for (int i=a+1;i<b;i++){ f[i]+=temp;d[i]+=k; temp+=k*(r[i]-l[i]+1); } pushdown(a);temp=k; for (int i=x;i<=min(y,r[a]);i++){ s[i]+=temp;temp+=k; } build(a);pushdown(b); if (a!=b){ temp=k*(l[b]-x+1); for (int i=l[b];i<=y;i++){ s[i]+=temp;temp+=k; } } temp=k*(y-x+1); for (int i=y+1;i<=r[b];i++) s[i]+=temp; build(b); for (int i=b+1;i<=cnt;i++) c[i]+=temp;}ll getval(int x){ ll ans(0); if (x==0||x==n+1) return -inf; int t=bl[x]; ans=s[x]+c[t]; ans+=(x-l[t])*d[t]+f[t]; return ans;}ll ask(int x){ int a=1,b=size[x]; while (a<=b){ int mid=(a+b)>>1; ll t1=getval(xu[x][mid-1]); ll t2=getval(xu[x][mid]); ll t3=getval(xu[x][mid+1]); if (t1<t2&&t2<t3) a=mid+1; else if (t3<t2&&t2<t1) b=mid-1; else return t2; }}ll query(int x,int y){ int a=bl[x],b=bl[y]; ll ans=-inf; for (int i=a+1;i<b;i++) ans=max(ans,ask(i)); for (int i=x;i<=min(y,r[a]);i++) ans=max(ans,getval(i)); if (a!=b){ for (int i=l[b];i<=y;i++) ans=max(ans,getval(i)); } return ans;}int main(){ n=read(); for (int i=1;i<=n;i++){ x=read(); s[i]=s[i-1]+x; } getbk(); for (int i=1;i<=cnt;i++) build(i); m=read(); for (int i=1;i<=m;i++){ kind=read();x=read();y=read(); if (kind==0){k=read();change(x,y,k);} else printf("%lld\n",query(x,y)); }}
0 0
- 【bzoj2388】【旅行规划】【分块+凸包】
- bzoj2388(凸包+分块)
- bzoj2388【分块+凸包二分】
- BZOJ2388: 旅行规划
- bzoj 2388 旅行规划 分块+二分+凸包
- bzoj 2388: 旅行规划 (分块+凸包+三分)
- 旅行规划问题
- 旅行规划问题(贪心)
- nyoj-253-LK的旅行(计算几何-凸包)
- NYOJ 253LK的旅行(凸包 对踵点)
- NYOJ-253LK的旅行【凸包+旋转卡壳】
- nyoj253-LK的旅行(凸包) 思路+代码
- 旅行商问题的动态规划解决
- 旅行商问题(动态规划)
- 动态规划求解TSP(旅行商)问题
- 状态压缩动态规划 -- 旅行商问题
- 动态规划思想求旅行商问题
- 货郎担(旅行售货商)动态规划
- Date内置对象
- listView天小时分钟秒倒计时的实现
- Android 富文本编辑器 图文混排
- 约瑟夫问题
- 第一次盲打比赛成绩
- 【bzoj2388】【旅行规划】【分块+凸包】
- Oracle创建表格时报错ora-00903:表名无效
- 大二下学习总结
- [Qt学习]14 Qt状态机框架——进入和退出状态
- 百度Map之Uncaught TypeError: Cannot read property 'fc' of undefined
- ARC MRC混编
- Josephus问题及其推广 分析和算法优化
- 从1到n整数中1出现的次数
- zh-cn:模板入门