zoukankan      html  css  js  c++  java
  • Subseq

    Portal --> broken qwq

    Description

       给你一个长度为(n)的整数序列,要支持以下两个操作:

    ((0,i,x)):将第(i)个数改成(x)

    ((1,l,r,k)):求出(k)个区间,满足这些区间没有公共部分并且都在([l,r])的范围内,求这些区间内的数的和的最大值(区间可以为空,空区间和为(0)

    ​   数据范围:

    对于40%的数据,(n,m,k<=1000)

    对于100%的数据,(n,m<=10^5,k<=20)

    Solution

       这题。。不难但是。。要写的简洁还是需要好好想一下qwq

    ​   丢上来主要是因为这题的重载运算符写得好的话会比直接写不知道简洁到哪里去了

    ​   然后还有就是。。这什么沙雕数据范围啊!!!难道100%不包含40%的吗!!!一开始没有仔细看于是乎出现了前四个1000的点RE后面的大点全部过掉的奇怪分数分布。。。

    ​   

    ​   好了言归正传

       这题因为这个(k<=20)所以可以直接非常暴力地变成查(k)次最大值,然后将这个最大值区间去掉,具体的话就是直接整个区间取相反数就好了,最后还原一下就好了

    ​   然后40%的数据也问题不大(吧)

    ​   然后你需要线段树维护最大值、最小值、左边最大值、左边最小值、右边最大值、右边最小值以及区间和。。。最小值的话是因为。。一旦区间取相反数之后。。最大值和最小值就要对调了

    ​   然后快乐封装之后就可以写的很好看啦!

      

    ​   代码大概长这样

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=100010,SEG=N*4,inf=1e9;
    struct Data{
    	int l,r,val;
    	Data(){}
    	Data(int l1,int r1,int val1){l=l1; r=r1; val=val1;}
    	friend Data operator + (Data x,Data y)
    	{return Data(x.l,y.r,x.val+y.val);}
    	friend bool operator < (Data x,Data y){return x.val<y.val;}
    	friend bool operator > (Data x,Data y){return x.val>y.val;}
    };
    Data Max(Data x,Data y){return x>y?x:y;}
    Data Min(Data x,Data y){return x<y?x:y;}
    struct Info{
    	Data l,r,ans;
    	Data sum;
    	Info(){}
    	Info(Data x){l=r=ans=sum=x;}
    	friend Info operator + (Info lch,Info rch){
    		Info ret;
    		ret.sum=lch.sum+rch.sum;
    		ret.l=Max(lch.l,lch.sum+rch.l);
    		ret.r=Max(rch.r,lch.r+rch.sum);
    		ret.ans=Max(Max(lch.ans,rch.ans),lch.r+rch.l);
    		return ret;
    	}
    }rec[1010];
    int a[N];
    namespace Seg{/*{{{*/
    	int ch[SEG][2];
    	Info mx[SEG],mn[SEG];
    	int tag[SEG];
    	int n,tot;
    	void pushup(int x){
    		mx[x]=mx[ch[x][0]]+mx[ch[x][1]];
    		mn[x]=mn[ch[x][0]]+mn[ch[x][1]];
    	}
    	void _build(int x,int l,int r){
    		tag[x]=0;
    		if (l==r){
    			mx[x]=Info(Data(l,r,a[l]));
    			mn[x]=Info(Data(l,r,-a[l]));
    			return;
    		}
    		int mid=l+r>>1;
    		ch[x][0]=++tot; _build(ch[x][0],l,mid);
    		ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
    		pushup(x);
    	}
    	void build(int _n){n=_n; tot=1; _build(1,1,n);}
    	void givetag(int x){
    		tag[x]^=1;
    		swap(mx[x],mn[x]);
    	}
    	void downtag(int x){
    		if (ch[x][0]) givetag(ch[x][0]);
    		if (ch[x][1]) givetag(ch[x][1]);
    		tag[x]=0;
    	}
    	void _update(int x,int l,int r,int lx,int rx){
    		if (l<=lx&&rx<=r){
    			givetag(x); return;
    		}
    		if (tag[x]) downtag(x);
    		int mid=lx+rx>>1;
    		if (l<=mid) _update(ch[x][0],l,r,lx,mid);
    		if (r>mid) _update(ch[x][1],l,r,mid+1,rx);
    		pushup(x);
    	}
    	void update(int l,int r){_update(1,l,r,1,n);}
    	void _modify(int x,int d,int lx,int rx,int delta){
    		if (lx==rx){
    			mx[x]=Info(Data(lx,rx,delta));
    			mn[x]=Info(Data(lx,rx,-delta));
    			return;
    		}
    		if (tag[x]) downtag(x);
    		int mid=lx+rx>>1;
    		if (d<=mid) _modify(ch[x][0],d,lx,mid,delta);
    		else _modify(ch[x][1],d,mid+1,rx,delta);
    		pushup(x);
    	}
    	void modify(int d,int delta){_modify(1,d,1,n,delta);}
    	Info _query(int x,int l,int r,int lx,int rx){
    		if (l<=lx&&rx<=r) return mx[x];
    		if (tag[x]) downtag(x);
    		int mid=lx+rx>>1;
    		if (r<=mid) return _query(ch[x][0],l,r,lx,mid);
    		else if (l>mid) return _query(ch[x][1],l,r,mid+1,rx);
    		else {
    			return _query(ch[x][0],l,mid,lx,mid)+_query(ch[x][1],mid+1,r,mid+1,rx);
    		}
    	}
    	Info query(int l,int r){return _query(1,l,r,1,n);}
    }/*}}}*/
    int n,m;
    void debug(){
    	Info tmp;
    	for (int i=1;i<=n;++i)
    		tmp=Seg::query(i,i),printf("%d ",tmp.ans.val);
    	printf("
    ");
    }
    void solve(int l,int r,int k){
    	int cnt=0,sum=0;
    	Info tmp;
    	for (int i=1;i<=k;++i){
    		tmp=Seg::query(l,r);
    		if (tmp.ans.val>0){
    			rec[++cnt]=tmp,sum+=tmp.ans.val;
    			Seg::update(tmp.ans.l,tmp.ans.r);
    			//debug();
    		}
    		else break;
    	}
    	for (int i=1;i<=cnt;++i){
    		Seg::update(rec[i].ans.l,rec[i].ans.r);
    		//debug();
    	}
    	printf("%d
    ",sum);
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int op,l,r,x,delta;
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i) scanf("%d",a+i);
    	Seg::build(n);
    	//debug();
    	scanf("%d",&m);
    	for (int i=1;i<=m;++i){
    		scanf("%d",&op);
    		if (op==0){
    			scanf("%d%d",&x,&delta);
    			Seg::modify(x,delta);
    		}
    		else{
    			scanf("%d%d%d",&l,&r,&delta);
    			solve(l,r,delta);
    		}
    	}
    }
    
  • 相关阅读:
    Day5:面向对象的定义(下)
    SQL 查询中not in 与 not exists 的区别
    SQL 语句的执行顺序
    SQL server 连接 查询
    SQL server 约束
    静态类与非静态类,静态成员及使用方法
    HR面试总结
    值类型与引用类型精解
    面试技巧
    MVC与设计模式的关系及MVC的实现原理和设计原理
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9508372.html
Copyright © 2011-2022 走看看