【BZOJ】【P2116】【Wc2011】【Joy】【题解】【差分+线段树+平衡树】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2116

首先这道题第6、7个点数据有问题,差分后的的序列会有0

然后看题

第一问,把原序列差分,差分序列的正数和就是答案

第二问实质上是扩展左区间的右端点和右区间的左端点使得得分下降,负数区间的权值为区间和减区间max,所以我们要维护区间和区间max,负数区间和支持前k小和的平衡树

线段树+set+Treap解决,修改的时候需要分4类讨论……正->正 正->负 负->正 负->负

Code(除了第7个点其他都能过):

#include<bits/stdc++.h>
#define fst first
#define sec second
using namespace std;
const int maxn=1e5+5;
typedef pair<int,int> par;
typedef long long LL;
int n,q,a[maxn],b[maxn];
LL ans1;
int getint(){
	int res=0,f=1;char c=getchar();
	while(!isdigit(c))f=f==-1||c=='-'?-1:1,c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res*f;
}
set<par>Neg;
struct Treap{
	struct node{
		LL val;LL sum;int key;
		int size,s;
		node *c[2];
		node(int _val=0,node *C=0){
			val=sum=_val;size=s=1;
			c[0]=c[1]=C;key=rand();
		}
		void rz(){
			size=c[0]->size+s+c[1]->size;
			sum=c[0]->sum+(LL)val*s+c[1]->sum;
		}
	}*null,*root;
	void rot(node *&t,bool d){
		node *p=t->c[d];t->c[d]=p->c[!d];
		p->c[!d]=t;t->rz();p->rz();t=p;
	}
	void insert(node *&t,LL x){
		if(t==null){t=new node(x,null);return;}
		if(t->val==x){t->size++;t->s++;t->sum+=x;return;}
		insert(t->c[t->val<x],x);
		if(t->c[t->val<x]->key<t->key)rot(t,t->val<x);
		else t->rz();
	}
	void del(node *&t,LL x){
		if(t==null)return;
		if(t->val==x){
			if(t->s>1){t->s--;t->size--;t->sum-=t->val;return;}
            bool d=t->c[0]->key>t->c[1]->key;  
            if(t->c[d]==null){delete t;t=null;return;}     
            rot(t,d);del(t->c[!d],x);  			
		}else del(t->c[t->val<x],x);t->rz();
	}
	void insert(LL x){insert(root,x);}
	int Q(LL x){
		if(root->sum+x>0)return -1;
		node *t=root;int ans=0;
		while(t!=null){
			if(t->c[0]->sum+x<=0)t=t->c[0];
			else{
				if(t->c[0]->sum+(LL)t->val*t->s+x<=0){
					return ans+t->c[0]->size+ceil((double)(t->c[0]->sum+x)/-t->val-1e-10);
				}else ans+=t->c[0]->size+t->s,x+=t->c[0]->sum+(LL)t->val*t->s,t=t->c[1];
			}
		}return ans;
	}
	void del(LL x){del(root,x);}
	void erase(node *t){
		if(t->c[0]!=null)erase(t->c[0]);
		if(t->c[1]!=null)erase(t->c[1]);
		delete t;
	}
	void clear(){
		if(root)erase(root);
		null=new node();
		null->size=null->s=0;null->key=INT_MAX;
		null->c[0]=null->c[1]=null;
		root=null;
	}
	void deb(node *t){
		if(t==null)return;
		printf("val:%d sum:%d size:%d s:%d\n",t->val,t->sum,t->size,t->s);
		if(t->c[0]!=null)deb(t->c[0]);
		if(t->c[1]!=null)deb(t->c[1]);
	}
	void deb(){deb(root);};
}T;
struct seg{
	struct node{
		LL sum;int mx;
		node(){sum=0;mx=INT_MIN;}
		node operator+(const node &rs){
			node c;c.sum=sum+rs.sum;
			c.mx=max(mx,rs.mx);return c;
		}
	}t[maxn<<2];
	#define lson i<<1,l,(l+r)/2
	#define rson i<<1|1,(l+r)/2+1,r
	#define ls i<<1
	#define rs i<<1|1
	void clear(){for(int i=0;i<(maxn<<2);i++)t[i].sum=0,t[i].mx=INT_MIN;}
	void build(int i,int l,int r){
		if(l==r){t[i].sum=t[i].mx=a[l];return;}	
		build(lson);build(rson);t[i]=t[ls]+t[rs];
	}
	void add(int i,int l,int r,int ps,int c){
		if(l==r){t[i].mx+=c;t[i].sum+=c;return;}
		if(ps<=(l+r)/2)add(lson,ps,c);
		else add(rson,ps,c);t[i]=t[ls]+t[rs];
	}
	int Qmax(int i,int l,int r,int l0,int r0){
		if(l0<=l&&r0>=r)return t[i].mx;
		int ans=INT_MIN;
		if(l0<=(l+r)/2)ans=max(ans,Qmax(lson,l0,r0));
		if(r0>(l+r)/2)ans=max(ans,Qmax(rson,l0,r0));
		return ans;
	}
	LL Qsum(int i,int l,int r,int l0,int r0){
		if(l0<=l&&r0>=r)return t[i].sum;
		LL ans=0;
		if(l0<=(l+r)/2)ans+=Qsum(lson,l0,r0);
		if(r0>(l+r)/2)ans+=Qsum(rson,l0,r0);
		return ans;
	}	
	int Qmax(int l,int r){return Qmax(1,1,n-1,l,r);}
	int Qsum(int l,int r){return Qsum(1,1,n-1,l,r);}
	void Add(int ps,int c){add(1,1,n-1,ps,c);}
}sgt;
int Qw(par pi){return sgt.Qsum(pi.fst,pi.sec)-sgt.Qmax(pi.fst,pi.sec);}
void del(par pi){if(pi.fst!=1&&pi.sec!=n-1)T.del(Qw(pi));}
void insert(par pi){if(pi.fst!=1&&pi.sec!=n-1)T.insert(Qw(pi));}
void Add(int ps,int c){
	if(a[ps]<0){
		if(a[ps]+c<0){
			set<par>::iterator it=--Neg.upper_bound(par(ps,n+1));
			if(it->fst!=1&&it->sec!=n-1){del(*it);sgt.Add(ps,c);insert(*it);}
			else sgt.Add(ps,c);
		}else{
			set<par>::iterator it=--Neg.upper_bound(par(ps,n+1));
			par p=*it;Neg.erase(p);del(p);sgt.Add(ps,c);
			if(p.fst<=ps-1){Neg.insert(par(p.fst,ps-1));
			insert(par(p.fst,ps-1));}
			if(ps+1<=p.sec)Neg.insert(par(ps+1,p.sec)),insert(par(ps+1,p.sec));
		}
	}else{
		if(a[ps]+c<0){
			if(ps>1&&a[ps-1]<0&&ps+1<n&&a[ps+1]<0){
				set<par>::iterator nxt=Neg.upper_bound(par(ps,n));
				set<par>::iterator pre=--nxt;nxt++;
				par p=par(pre->fst,nxt->sec);
				del(*pre);Neg.erase(*pre);
				del(*nxt);Neg.erase(*nxt);
				sgt.Add(ps,c);
				insert(p);Neg.insert(p);
			}else
			if(ps>1&&a[ps-1]<0){
				set<par>::iterator nxt=Neg.upper_bound(par(ps,n));
				set<par>::iterator pre=--nxt;nxt++;
				par p=par(pre->fst,ps);
				del(*pre);Neg.erase(*pre);sgt.Add(ps,c);
				insert(p);Neg.insert(p);				
			}else
			if(ps+1<n&&a[ps+1]<0){
				set<par>::iterator nxt=Neg.upper_bound(par(ps,n));
				par p=par(ps,nxt->sec);
				del(*nxt);Neg.erase(*nxt);sgt.Add(ps,c);
				insert(p);Neg.insert(p);			
			}else sgt.Add(ps,c),Neg.insert(par(ps,ps)),insert(par(ps,ps));
		}else sgt.Add(ps,c);
	}
}
void solve(){
	ans1=0;sgt.clear();T.clear();Neg.clear();
	n=getint();q=getint();
	for(int i=1;i<=n;i++)b[i]=getint();
	for(int i=1;i<n;i++)a[i]=b[i+1]-b[i];
	sgt.build(1,1,n-1);
	int st=n;
	for(int i=1;i<n;i++){
		ans1+=a[i]*(a[i]>0);
		if(a[i]>0){
			if(st<=i-1){
				Neg.insert(par(st,i-1));
				insert(par(st,i-1));
				st=n;
			}
		}else if(st==n)st=i;		
	}
	if(st<=n-1)Neg.insert(par(st,n-1)),
	insert(par(st,n-1));	
	while(q--){
		int op=getint();
		if(op==1){
			printf("%I64d %d\n",ans1,T.Q(ans1));				
		}else{
			int l=getint(),r=getint(),c=getint();
			if(l>1)Add(l-1,c),ans1-=a[l-1]*(a[l-1]>0),a[l-1]+=c,ans1+=a[l-1]*(a[l-1]>0);//,assert(a[l-1]!=0);
			if(r<n)Add(r,-c),ans1-=a[r]*(a[r]>0),a[r]-=c,ans1+=a[r]*(a[r]>0);//,assert(a[r]!=0);
		}
	}
}
int main(){
	int T;scanf("%d",&T);
	while(T--)solve();
	return 0;
}



1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值