题目大意
一个序列,有很多询问,每个询问要问区间>=x的数的个数。
现有若干修改操作,区间赋值,每次修改后请你将所有询问得到的答案和输出。
颜色段
均摊分析颜色段!
可以用set维护颜色段。
然后只需要考虑一个区间全部由x变成y产生代价。
先把询问按x排序做可持久化线段树,然后就很好做。
#pragma GCC optimize(2)
#include<cstdio>
#include<algorithm>
#include<set>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=100000+10,maxtot=24000000+10;
int pre[maxn*4],nxt[maxn*4],L[maxn*4],R[maxn*4],val[maxn*4];
struct dong{
int l,r,x;
} ask[maxn];
struct suan{
int x,y;
friend bool operator <(suan a,suan b){
return a.x<b.x||a.x==b.x&&a.y<b.y;
}
} zlt;
multiset<suan> s1;
ll tree[maxtot];
int a[maxn],root[maxn],left[maxtot],right[maxtot],ad[maxtot],sta[80];
int i,j,k,l,r,x,y,xx,yy,s,t,n,m,q,tot,top,cnt;
ll ans,LL,rr,tt;
bool czy;
ll read(){
ll x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int newnode(int x){
tot++;
left[tot]=left[x];
right[tot]=right[x];
tree[tot]=tree[x];
ad[tot]=ad[x];
return tot;
}
void mark(int &x,int l,int r,int v){
x=newnode(x);
tree[x]+=(ll)(r-l+1)*v;
ad[x]+=v;
}
void down(int x,int l,int r){
int mid=(l+r)/2;
if (ad[x]){
mark(left[x],l,mid,ad[x]);
mark(right[x],mid+1,r,ad[x]);
ad[x]=0;
}
}
void insert(int &x,int l,int r,int a,int b){
//x=newnode(x);
if (l==a&&r==b){
mark(x,l,r,1);
return;
}
down(x,l,r);
x=newnode(x);
int mid=(l+r)/2;
if (b<=mid) insert(left[x],l,mid,a,b);
else if (a>mid) insert(right[x],mid+1,r,a,b);
else{
insert(left[x],l,mid,a,mid);
insert(right[x],mid+1,r,mid+1,b);
}
tree[x]=tree[left[x]]+tree[right[x]];
}
ll query(int x,int l,int r,int a,int b){
//if (!x) return 0;
if (l==a&&r==b) return tree[x];
down(x,l,r);
int mid=(l+r)/2;
if (b<=mid) return query(left[x],l,mid,a,b);
else if (a>mid) return query(right[x],mid+1,r,a,b);
else return query(left[x],l,mid,a,mid)+query(right[x],mid+1,r,mid+1,b);
}
void change(int l,int r,int x,int y,int f){
if (x==y) return;
if (x>y) swap(x,y),f*=-1;
ll t=query(root[x+1],1,n,l,r)-query(root[y+1],1,n,l,r);
ans+=t*f;
}
bool cmp(dong a,dong b){
return a.x<b.x;
}
void write(ll x){
if (!x){
putchar('0');
putchar('\n');
return;
}
top=0;
while (x){
sta[++top]=x%10;
x/=10;
}
while (top) putchar('0'+sta[top--]);
putchar('\n');
}
int main(){
freopen("create.in","r",stdin);freopen("create.out","w",stdout);
n=read();m=read();q=read();
czy=1;
cnt=0;
fo(i,1,n){
a[i]=read();
if (a[i]!=a[i-1]){
R[cnt]=i-1;
L[++cnt]=i;
pre[cnt]=cnt-1;
nxt[cnt-1]=cnt;
val[cnt]=a[i];
zlt.x=R[cnt-1];
zlt.y=cnt-1;
s1.insert(zlt);
}
}
R[cnt]=n;
zlt.x=n;
zlt.y=cnt;
s1.insert(zlt);
fo(i,1,m){
ask[i].l=read();ask[i].r=read();
ask[i].x=read();
}
sort(ask+1,ask+m+1,cmp);
j=m;
fd(i,n,1){
root[i]=root[i+1];
while (j&&ask[j].x==i){
insert(root[i],1,n,ask[j].l,ask[j].r);
j--;
}
}
fo(i,1,cnt)
change(L[i],R[i],0,val[i],1);
//printf("%lld\n",ans);
write(ans);
//return 0;
while (q--){
LL=read();rr=read();tt=read();
if (czy){
LL^=ans;
rr^=ans;
tt^=ans;
}
l=LL;r=rr;t=tt;
zlt.x=l;zlt.y=0;
x=(*s1.lower_bound(zlt)).y;
zlt.x=r;zlt.y=0;
y=(*s1.lower_bound(zlt)).y;
if (x==y){
change(l,r,val[x],t,1);
zlt.x=R[x];zlt.y=x;
s1.erase(s1.find(zlt));
if (l!=L[x]){
cnt++;
R[cnt]=l-1;
L[cnt]=L[x];
val[cnt]=val[x];
zlt.x=R[cnt];zlt.y=cnt;
s1.insert(zlt);
xx=cnt;
pre[cnt]=pre[x];
if (pre[x]) nxt[pre[x]]=cnt;
}
else xx=pre[x];
if (r!=R[x]){
cnt++;
R[cnt]=R[x];
L[cnt]=r+1;
val[cnt]=val[x];
zlt.x=R[cnt];zlt.y=cnt;
s1.insert(zlt);
yy=cnt;
nxt[cnt]=nxt[x];
if (nxt[x]) pre[nxt[x]]=cnt;
}
else yy=nxt[x];
L[++cnt]=l;
R[cnt]=r;
val[cnt]=t;
zlt.x=r;zlt.y=cnt;
s1.insert(zlt);
pre[cnt]=xx;
if (xx) nxt[xx]=cnt;
nxt[cnt]=yy;
if (yy) pre[yy]=cnt;
//printf("%lld\n",ans);
write(ans);
continue;
}
change(l,R[x],val[x],t,1);
zlt.x=R[x];zlt.y=x;
s1.erase(s1.find(zlt));
change(L[y],r,val[y],t,1);
zlt.x=R[y];zlt.y=y;
s1.erase(s1.find(zlt));
j=nxt[x];
while (j!=y){
change(L[j],R[j],val[j],t,1);
zlt.x=R[j];zlt.y=j;
s1.erase(s1.find(zlt));
j=nxt[j];
}
if (l!=L[x]){
R[x]=l-1;
zlt.x=R[x];zlt.y=x;
s1.insert(zlt);
xx=x;
}
else xx=pre[x];
if (r!=R[y]){
L[y]=r+1;
zlt.x=R[y];zlt.y=y;
s1.insert(zlt);
yy=y;
}
else yy=nxt[y];
cnt++;
L[cnt]=l;
R[cnt]=r;
val[cnt]=t;
pre[cnt]=xx;
if (xx) nxt[xx]=cnt;
nxt[cnt]=yy;
if (yy) pre[yy]=cnt;
zlt.x=r;zlt.y=cnt;
s1.insert(zlt);
//printf("%lld\n",ans);
write(ans);
}
}