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;
}