3992. 【GDOI2015模拟2.25】Christmas

Description

Input

Output

Sample Input

3
1 2 3
5
A 1 2 4
M 2 3 5
Q 1
Q 2
Q 3

Sample Output

5 1
6 1
5 1
样例说明:
第一个操作后序列变成了5,6,3
第二次操作后序列变成了5,6,5

Data Constraint

Solution

对于加法和取max就是吉司机线段树

对于修改次数:

可以维护区间最小值的max操作的修改次数,以及对当前区间进行的加法操作的次数。

这个次数也要像懒惰标记一样下穿,更新时不用往上更新。

那么对于加法修改次数标记直接下传即可。

对于max修改次数标记,在儿子区间的min值小于max标记时,将儿子区间的次数标记加上当前区间的次数标记。

最后,这里也可以将最大值标记直接去掉,用区间的最小值代替。

打标记时就直接将区间最小值修改,

而下传时只需发现如果当前区间的最小值要比儿子区间的最小值大,那么就下传最小值(相当于是最大值修改的标记)

注意(小细节):

1.加的数如果是0可以不操作,因为数值没有变化。

2.加法标记可能会因为加上一个负数而抵消,因此要判断是否打过标记,而不能判断标记数组是否有值。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define I int
#define ll long long
#define ls x<<1  
#define rs ls|1 
#define Ls ls,l,M
#define Rs rs,M+1,r
#define F(i,a,b) for(I i=a;i<=b;i++)
#define N 100005
#define inf 0x7fffffff
using namespace std;
I n,m,l,r,c,a[N],S1,S2;
char ch;
struct data{I mn,mn2,cmn,tad,Ta,Tm;}t[N<<2];
void R(I &x){
	I w=1;x=0;ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	x*=w;
}
void update(I x){
	if(t[ls].mn==t[rs].mn){
		t[x].mn=t[ls].mn,t[x].cmn=t[ls].cmn+t[rs].cmn;
		t[x].mn2=min(t[ls].mn2,t[rs].mn2);
	}
	else if(t[ls].mn<t[rs].mn){
		t[x].mn=t[ls].mn,t[x].cmn=t[ls].cmn;
		t[x].mn2=min(t[ls].mn2,t[rs].mn);
	}
	else{
		t[x].mn=t[rs].mn,t[x].cmn=t[rs].cmn;
		t[x].mn2=min(t[ls].mn,t[rs].mn2);
	}
}
void push_add(I x,I v){
	t[x].mn+=v,t[x].tad+=v;
	if(t[x].mn2!=inf) t[x].mn2+=v;
}
void down(I x){
	if(t[x].Ta){//注意这里加的标记可能会因为加上一个负数而抵消,因此要判断是否打过标记,而不能判断标记数组是否有值 
		push_add(ls,t[x].tad),push_add(rs,t[x].tad);
		t[ls].Ta+=t[x].Ta,t[rs].Ta+=t[x].Ta;
	}
	if(t[ls].mn<t[x].mn){t[ls].mn=t[x].mn,t[ls].Tm+=t[x].Tm;}
	if(t[rs].mn<t[x].mn){t[rs].mn=t[x].mn,t[rs].Tm+=t[x].Tm;}
	t[x].tad=t[x].Ta=t[x].Tm=0;
}
void work(I tp,I l2,I r2,I v,I x=1,I l=1,I r=n){
	if(l>r2||r<l2||(!tp&&t[x].mn>=v)) return;
	if(l2<=l&&r<=r2){
		if(tp){t[x].Ta++;return push_add(x,v);}
		else{if(t[x].mn2>v){t[x].Tm++;t[x].mn=v;return;}}
	}
	I M=l+r>>1;
	down(x);
	work(tp,l2,r2,v,Ls),work(tp,l2,r2,v,Rs);
	update(x);
}
void qry(I k,I x=1,I l=1,I r=n){
	if(l==r){S1=t[x].mn,S2=t[x].Ta+t[x].Tm;return;}
	I M=l+r>>1;
	down(x);
	if(k<=M) qry(k,Ls);else qry(k,Rs);
}
void build(I x=1,I l=1,I r=n){
	if(l==r){t[x]=data{a[l],inf,1,0,0,0};return;}
	I M=l+r>>1;
	build(Ls),build(Rs);
	update(x);
}
I main(){
	freopen("Christmas.in","r",stdin);
	freopen("Christmas.out","w",stdout);
	R(n);
	F(i,1,n) R(a[i]);
	build();
	R(m);
	while(m--){
		ch=getchar();
		while(ch<'A'||ch>'Q') ch=getchar();
		if(ch=='A'){R(l),R(r),R(c);if(c!=0) work(1,l,r,c);}
		else if(ch=='M'){R(l),R(r),R(c);work(0,l,r,c);}
		else{R(c),qry(c);printf("%d %d\n",S1,S2);}
	}
	return 0;	
}

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/107760454