zoukankan      html  css  js  c++  java
  • 【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)

    【BZOJ3638】Cf172 k-Maximum Subsequence Sum

    Description

    给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少。1 ≤ n ≤ 105,1 ≤ m ≤ 105,1 ≤ l ≤ r ≤ n1 ≤ k ≤ 20

    Sample Input

    9
    9 -8 9 -1 -1 -1 9 -8 9
    3
    1 1 9 1
    1 1 9 2
    1 4 6 3

    Sample Output

    17
    25
    0

    题解:如果直接用背包DP跑线段树区间合并的话,复杂度是O(nk^2logn)的

    先考虑费用流的做法,我们第一次取的时候一定选择的是区间中的最大连续子段,然后模拟费用流的过程,我们建立反向边,即将原来的最大连续子段取反,然后再找最大连续子段。。。最后询问完毕,再将哪些取反操作都还原回去。

    所以一共要维护哪些东西呢?最大连续子段和以及它的位置,不过由于有取反操作,所以我们还要维护最小连续子段和以及它的位置,然后就没了。。。

    为了代码美观,区间合并的时候用了很多重载运算符,还是挺吓人的~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define lson x<<1
    #define rson x<<1|1
    const int maxn=100010;
    using namespace std;
    int n,m,ans;
    int v[maxn],pa[maxn],pb[maxn];
    struct pp
    {
    	int val,l,r;
    	pp() {}
    	pp(int x) {l=r=x,val=v[x];}
    	pp(int a,int b,int c) {val=a,l=b,r=c;}
    	pp operator + (const pp &a) const {return pp(val+a.val,l,a.r);}
    	bool operator < (const pp a) const {return val<a.val;}
    };
    struct node
    {
    	bool tag;
    	pp s,sm,sn,lm,ln,rm,rn;
    	node() {}
    	node(int x)
    	{
    		s=pp(x),tag=0;
    		if(v[x]<0)	ln=rn=sn=s,lm=sm=pp(0,x,x-1),rm=pp(0,x+1,x);
    		else	lm=rm=sm=s,ln=sn=pp(0,x,x-1),rn=pp(0,x+1,x);
    	}
    }s[maxn<<2];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    inline int max(int a,int b,int c)	{return max(max(a,b),c);}
    inline int min(int a,int b,int c)	{return min(min(a,b),c);}
    inline pp max(const pp &a,const pp &b,const pp &c)	{return max(max(a,b),c);}
    inline pp min(const pp &a,const pp &b,const pp &c)	{return min(min(a,b),c);}
    inline node merge(const node &a,const node &b)
    {
    	node c;
    	c.lm=max(a.lm,a.s+b.lm),c.rm=max(b.rm,a.rm+b.s),c.sm=max(a.sm,b.sm,a.rm+b.lm);
    	c.ln=min(a.ln,a.s+b.ln),c.rn=min(b.rn,a.rn+b.s),c.sn=min(a.sn,b.sn,a.rn+b.ln);
    	c.s=a.s+b.s,c.tag=0;
    	return c;
    }
    inline void rev(node &x)
    {
    	x.sm.val=-x.sm.val,x.lm.val=-x.lm.val,x.rm.val=-x.rm.val;
    	x.sn.val=-x.sn.val,x.ln.val=-x.ln.val,x.rn.val=-x.rn.val;
    	x.s.val=-x.s.val,x.tag^=1;
    	swap(x.sm,x.sn),swap(x.lm,x.ln),swap(x.rm,x.rn);
    }
    inline void pushdown(int x)
    {
    	if(s[x].tag)	rev(s[lson]),rev(s[rson]),s[x].tag=0;
    }
    void build(int l,int r,int x)
    {
    	if(l==r)
    	{
    		s[x]=node(l);
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,lson),build(mid+1,r,rson);
    	s[x]=merge(s[lson],s[rson]);
    }
    void updata(int l,int r,int x,int a,int b)
    {
    	if(a<=l&&r<=b)
    	{
    		rev(s[x]);
    		return ;
    	}
    	pushdown(x);
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,lson,a,b);
    	if(b>mid)	updata(mid+1,r,rson,a,b);
    	s[x]=merge(s[lson],s[rson]);
    }
    node query(int l,int r,int x,int a,int b)
    {
    	if(a<=l&&r<=b)	return s[x];
    	pushdown(x);
    	int mid=(l+r)>>1;
    	if(b<=mid)	return query(l,mid,lson,a,b);
    	if(a>mid)	return query(mid+1,r,rson,a,b);
    	return merge(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
    }
    void modify(int l,int r,int x,int a)
    {
    	if(l==r)
    	{
    		s[x]=node(l);
    		return ;
    	}
    	pushdown(x);
    	int mid=(l+r)>>1;
    	if(a<=mid)	modify(l,mid,lson,a);
    	else 	modify(mid+1,r,rson,a);
    	s[x]=merge(s[lson],s[rson]);
    }
    int main()
    {
    	n=rd();
    	int i,j,a,b,c;
    	pp tmp;
    	for(i=1;i<=n;i++)	v[i]=rd();
    	build(1,n,1);
    	m=rd();
    	for(i=1;i<=m;i++)
    	{
    		if(rd()==1)
    		{
    			a=rd(),b=rd(),c=rd(),ans=0;
    			for(j=1;j<=c;j++)
    			{
    				tmp=query(1,n,1,a,b).sm,ans+=tmp.val;
    				if(!tmp.val)	break;
    				pa[j]=tmp.l,pb[j]=tmp.r,updata(1,n,1,tmp.l,tmp.r);
    			}
    			for(j--;j;j--)	updata(1,n,1,pa[j],pb[j]);
    			printf("%d
    ",ans);
    		}
    		else	a=rd(),b=rd(),v[a]=b,modify(1,n,1,a);
    	}
    	return 0;
    }//9 9 -8 9 -1 -1 -1 9 -8 9 3 1 1 9 1 1 1 9 2 1 4 6 3 
  • 相关阅读:
    构建之法 阅读笔记01
    个人作业1 -数组
    进度一
    开课博客
    生活尝试
    人月神话3
    安卓开发工具
    人月神话 2
    Qt 的入门小程序
    提问的智慧 摘抄(How To Ask Questions The Smart Way)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7560373.html
Copyright © 2011-2022 走看看