BZOJ 3638 k-Maximum Subsequence Sum
来源:互联网 发布:st6015塔吊相关数据? 编辑:程序博客网 时间:2024/05/20 13:03
题目大意:给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少。
如果仅仅是询问一次,我们可以构图费用流,跑一次就行了。但题目是多组询问,直接费用流显然会TLE。自然地,我们想到对残余网络进行增广,但每次地询问区间不同,而且有修改操作,这种做法也不可行。本蒟蒻膜拜了一下hzwer大大的题解,发现根据费用流每次求最长路的性质,可以手动增广,也就是每次用线段树求一个最大子段和,然后将整个区间取反,继续增广,直到和为0或者个数达到K次为止。(可以这么理解,增广之后正向弧达到满流,反向弧流减少,而反向弧中费用为负值)接下来就是线段树的基本操作了。我们要维护区间最大和以及位置(正向弧和反向弧的信息都要维护),还要维护一个flag记录上次增广的是哪条弧,但只要想清楚还是很好写的。
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int maxn=200000+10;struct node{ int lx,lp,rx,rp,sum; int mx,p1,p2;};struct data{ node mx,mn; int flag;}t[maxn*4];struct arr{ int l,r;};vector<arr> h;int n,m,op,a[maxn],cc;void init(node &p,int l,int v){ p.lp=p.rp=p.p1=p.p2=l; p.mx=p.lx=p.rx=p.sum=v;}node merge(node a,node b){ node res;res.sum=a.sum+b.sum; res.lx=a.lx;res.lp=a.lp; if(a.sum+b.lx>res.lx) res.lx=a.sum+b.lx,res.lp=b.lp; res.rx=b.rx;res.rp=b.rp; if(b.sum+a.rx>res.rx) res.rx=b.sum+a.rx,res.rp=a.rp; res.mx=a.mx;res.p1=a.p1;res.p2=a.p2; if(b.mx>res.mx) res.mx=b.mx,res.p2=b.p2,res.p1=b.p1; if(a.rx+b.lx>res.mx) res.mx=a.rx+b.lx,res.p1=a.rp,res.p2=b.lp; return res;}void pushup(int p){ t[p].mx=merge(t[p*2].mx,t[p*2+1].mx); t[p].mn=merge(t[p*2].mn,t[p*2+1].mn);}void pushdown(int p){ if(t[p].flag) { swap(t[p*2].mn,t[p*2].mx); swap(t[p*2+1].mn,t[p*2+1].mx); t[p].flag^=1;t[p*2].flag^=1;t[p*2+1].flag^=1; }}void build(int p,int l,int r){ if(l==r) { init(t[p].mx,l,a[l]); init(t[p].mn,l,-a[l]); return; } int mid=(l+r)>>1; build(p*2,l,mid);build(p*2+1,mid+1,r); pushup(p);}void update(int p,int l,int r,int x,int v){ if(x<l||x>r) return; if(l==r) { init(t[p].mx,l,v); init(t[p].mn,l,-v); return; } pushdown(p); int mid=(l+r)>>1; update(p*2,l,mid,x,v); update(p*2+1,mid+1,r,x,v); pushup(p);}void reverse(int p,int l,int r,int x,int y){ if(l>y||r<x) return; if(l>=x&&r<=y) { swap(t[p].mn,t[p].mx); t[p].flag^=1; return; } pushdown(p);int mid=(l+r)>>1; reverse(p*2,l,mid,x,y); reverse(p*2+1,mid+1,r,x,y); pushup(p);}node query(int p,int l,int r,int x,int y){ if(l>=x&&r<=y) { return t[p].mx; } int mid=(l+r)>>1; pushdown(p); if(y<=mid) return query(p*2,l,mid,x,y); else if(x>mid) return query(p*2+1,mid+1,r,x,y); else return merge(query(p*2,l,mid,x,y),query(p*2+1,mid+1,r,x,y));}void solve(int l,int r,int k){ int res=0;h.clear(); for(int i=1;i<=k;i++) { node hm=query(1,1,n,l,r); if(hm.mx<=0) break; else res+=hm.mx; reverse(1,1,n,hm.p1,hm.p2); h.push_back((arr){hm.p1,hm.p2}); //cout<<hm.p1<<' '<<hm.p2<<endl; } for(int i=h.size()-1;i>=0;i--) reverse(1,1,n,h[i].l,h[i].r); printf("%d\n",res);}int main(){ //freopen("3638.in","r",stdin); //freopen("3638.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n);int op,l,r,k; scanf("%d",&m); for(int i=1;i<=m;i++) { cc++; scanf("%d%d%d",&op,&l,&r); if(op!=1) update(1,1,n,l,r),a[l]=r; else { scanf("%d",&k); solve(l,r,k); } } return 0;}
0 0
- BZOJ 3638 k-Maximum Subsequence Sum
- BZOJ 3638 k-Maximum Subsequence Sum
- k-Maximum Subsequence Sum
- [bzoj3638]k-Maximum Subsequence Sum
- [费用流手动增广 线段树] BZOJ 3267 KC采花 && 3272 Zgg吃东西 && 3638 Cf172 k-Maximum Subsequence Sum
- [CF280D/CF172][BZOJ3272/3638][JZOJ4400]k-Maximum Subsequence Sum
- CF280D k-Maximum Subsequence Sum (线段树)
- BZOJ3638 Cf172 k-Maximum Subsequence Sum
- 【Codeforces Round #172】Codeforces 280D k-Maximum Subsequence Sum
- [题解]codeforces 280d k-Maximum Subsequence Sum
- Maximum Subsequence Sum
- 1007. Maximum Subsequence Sum
- PAT1007. Maximum Subsequence Sum
- PAT_1007: Maximum Subsequence Sum
- 1007 Maximum Subsequence Sum
- PAT - Maximum Subsequence Sum
- PAT1007. Maximum Subsequence Sum
- Maximum Subsequence Sum (25)
- 川大oj 4370: Huangshenno1's test
- 畅通工程hd1863
- JDK+MyEclipse+Tomcat的配置
- 一种基于EF+MVC的小型系统快速开发架构
- Android Fragment 真正的完全解析(下)
- BZOJ 3638 k-Maximum Subsequence Sum
- Java基础—java基础语法
- Hibernate 参数设置一览表
- java apache commons HttpClient发送get和post请求的学习整理
- Java 内存区域和GC机制
- sublime text2/3怎样在windows中配置ctags插件
- Android中BroadcastReceiver案例讲解
- 关于javascript操作表格的代码联系记录
- JVM监控与调优