题意
给一个长度为
n
(
n
≤
1.5
×
1
0
5
)
n(n \leq 1.5 \times 10^5)
n(n≤1.5×105) 的序列,每个点有权值
a
i
a_i
ai,初始均为白色。
需要支持
q
(
q
≤
2
×
1
0
4
)
q(q \leq 2 \times 10^4)
q(q≤2×104) 次以下两种操作:
1.
1.
1. 将
a
x
a_x
ax 修改为
y
y
y。
2.
2.
2. 将
x
x
x 位置染黑。
定义一个连续白色段的权值为其中逆序对的个数,你需要在每次操作后输出所有白色连续的的权值的异或和。强制在线。
题解
小清新数据结构。
显然每次操作时,先把所在连续白色连续段的权值扣掉,算出新的权值再异或回去。
显然我们可以用 s e t set set 套 p a i r pair pair 来维护所在的连续段。
先考虑 1 1 1 操作,其实就是扣去 a x a_x ax 在其所在段中的逆序对个数,再加上 y y y 在该段中的逆序对个数。这里可以用树套树维护(树套 s p l a y splay splay 不知道为什么过不去,就改成树套树了)。
再考虑
2
2
2 操作,不难发现,我们无法求出一段和一段之间的逆序对个数,所以我们就要考虑一个对一段的逆序对个数。不过直接做显然效率会退化到
O
(
n
2
)
O(n^2)
O(n2),所以我们仔细考虑一下,这里只有分裂,没有合并,注意到他的有效空间不会太大,所以想到类似启发式合并的方法,也就是启发式分裂。
每次我们把分裂的两段区间中小的那个区间里的点拿出来,扣掉和大的区间之间的逆序对个数,然后在暴力
O
(
l
e
n
m
i
n
l
o
g
l
e
n
m
i
n
)
O(len_{min} log_{len_{min}})
O(lenminloglenmin) 把新区间的逆序对算出来就好。至于怎么求出一个点和一块的逆序对数量,拿个随便什么东西维护一下就好了。这里建议用
s
p
l
a
y
splay
splay ,因为你前面已经有一个
n
l
o
g
2
n
nlog^2n
nlog2n 的空间了,再多一个可能会开不下,而
s
p
l
a
y
splay
splay 的优点就在于方便以及节约空间。然后你就可以愉快地切掉这道题了~~~~
代码
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=150005;
const int MAXN=1e9;
inline int read(){
int k=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
return k*f;
}
int ch[N<<6][2],fa[N<<6],val[N<<6],now,cnt[N<<6],rt[N<<6],sz[N<<6],n,q,nw,be[N],a[N];
LL shu[N<<6],ans,lastans,tim;
int root[N],t;
struct Node{
int lc,rc,sum;
}T[N*400];
set<pair<int,int> > qu;
inline int get(int x){
return ch[fa[x]][1]==x;
}
inline void update(int x){
sz[x]=cnt[x];
if(ch[x][0])sz[x]+=sz[ch[x][0]];
if(ch[x][1])sz[x]+=sz[ch[x][1]];
}
inline void rotate(int x){
int F=fa[x],k=get(x),G=ch[x][k^1];
if(fa[F])ch[fa[F]][get(F)]=x;
fa[x]=fa[F];fa[F]=x;fa[G]=F;
ch[x][k^1]=F;ch[F][k]=G;
update(F);update(x);
}
inline void splay(int x,int &p){
while(fa[x]){
if(fa[fa[x]])rotate((get(x)==get(fa[x]))?fa[x]:x);
rotate(x);
}
p=x;
}
inline void insert(int &p,int x){
if(!p){
p=++now;
cnt[p]=1;val[p]=x;
return;
}
int k=p;
while(1){
if(val[k]==x){
cnt[k]++,splay(k,p);
return;
}
if(!ch[k][x>val[k]]){
now++;
cnt[now]=1;val[now]=x;
ch[k][x>val[k]]=now;fa[now]=k;
splay(now,p);
return;
}
k=ch[k][x>val[k]];
}
}
inline int find(int x,int &p){
if(!p)return 0;
int s=0,k=p;
while(1){
// tim++;
if(!k)return s;
//cout<<"FIND "<<val[k]<<" "<<x<<" "<<cnt[k]<<" "<<ch[k][1]<<" "<<val[ch[k][1]]<<" "<<cnt[ch[k][1]]<<endl;
if(x>val[k])k=ch[k][1];
else{
s+=(x<=val[k])?sz[ch[k][1]]:0;
if(val[k]==x){
splay(k,p);
return s;
}
s+=cnt[k];
k=ch[k][0];
}
}
return 0;
}
inline int find_f(int x,int &p){
if(!p)return 0;
int s=0,k=p;
while(1){
// tim++;
if(!k)return s;
// cout<<"find_F "<<x<<" "<<val[k]<<" "<<val[ch[k][0]]<<" "<<sz[ch[k][0]]<<endl;
if(x<val[k])k=ch[k][0];
else{
s+=(x>=val[k])?sz[ch[k][0]]:0;
if(val[k]==x){
splay(k,p);
return s;
}
s+=cnt[k];
k=ch[k][1];
}
}
return 0;
}
inline int find_id(int x,int &p){
if(!p)return 0;
int k=p;
while(1){
if(val[k]==x){
splay(k,p);
return k;
}
k=ch[k][x>val[k]];
}
return 0;
}
inline int pre(int p){
p=ch[p][0];
while(ch[p][1])p=ch[p][1];
return p;
}
inline void del(int x,int &p){
int k=find_id(x,p);
if(cnt[k]>1){cnt[k]--;return;}
if(!ch[k][0]&&!ch[k][1]){p=0;return;}
if(!ch[k][0]||!ch[k][1]){
int kp=ch[k][0]|ch[k][1];
fa[kp]=0;p=kp;
return;
}
int kp=pre(k);splay(kp,p);
// cout<<"DEl "<<val[kp]<<" "<<val[k]<<endl;
fa[ch[k][1]]=kp;ch[kp][1]=ch[k][1];p=kp;
update(p);
}
inline int lowbit(int x){return x&(-x);}
void add(int &p,int l,int r,int x,int d){
if(!p)p=++t;
T[p].sum+=d;
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)add(T[p].lc,l,mid,x,d);
else add(T[p].rc,mid+1,r,x,d);
}
int query(int p,int l,int r,int L,int R){
if(!p)return 0;
if(l>=L&&r<=R)return T[p].sum;
int mid=(l+r)>>1,s=0;
if(L<=mid)s+=query(T[p].lc,l,mid,L,R);
if(R>mid)s+=query(T[p].rc,mid+1,r,L,R);
return s;
}
inline int ask(int l,int r,int L,int R){
if(L>R||l>r)return 0;
if(R<=0||L<=0)return 0;
int s=0;l--;
for(;r;r-=lowbit(r))s+=query(root[r],1,MAXN,L,R);
for(;l;l-=lowbit(l))s-=query(root[l],1,MAXN,L,R);
return s;
}
inline void solve_1(int x,int y){
auto lt=qu.upper_bound(make_pair(x,n+1));
if(lt==qu.begin())return;
--lt;
if(x>(*lt).second)return;
int l=(*lt).first,r=(*lt).second;
ans^=shu[be[l]];
// cout<<"FAQ "<<shu[be[l]];
for(int j=x;j<=n;j+=lowbit(j))add(root[j],1,MAXN,a[x],-1);
if(x!=l){
shu[be[l]]+=ask(l,x-1,y+1,MAXN)-ask(l,x-1,a[x]+1,MAXN);
// cout<<"ask l "<<ask(l,x-1,y+1,MAXN)<<" "<<ask(l,x-1,a[x]+1,MAXN)<<endl;
}
if(x!=r){
shu[be[l]]+=ask(x+1,r,1,y-1)-ask(x+1,r,1,a[x]-1);
// cout<<"ask r "<<ask(x+1,r,1,y-1)<<" "<<ask(x+1,r,1,a[x]-1)<<endl;
}
// cout<<"faq "<<shu[be[l]]<<endl;
for(int j=x;j<=n;j+=lowbit(j))add(root[j],1,MAXN,y,1);
del(a[x],rt[be[l]]);
insert(rt[be[l]],y);
a[x]=y;
ans^=shu[be[l]];
lastans=ans;
}
inline void solve_2(int x){
// cout<<"Solve_2 "<<x<<endl;
// for(auto it=qu.begin();it!=qu.end();++it)cout<<"Qu "<<(*it).first<<" "<<(*it).second<<endl;
auto lt=qu.upper_bound(make_pair(x,n+1));
--lt;
int l=(*lt).first,r=(*lt).second;
ans^=shu[be[l]];
// cout<<"FAQ "<<ans<<" "<<l<<" "<<r<<" "<<x<<endl;
if(l==r){
qu.erase(make_pair(l,r));
lastans=ans;
return;
}
if(x==l){
qu.erase(make_pair(l,r));
qu.insert(make_pair(l+1,r));
be[l+1]=be[l];be[l]=0;
shu[be[l+1]]-=find_f(a[x],rt[be[l+1]]);
// cout<<"Cha_f "<<a[x]<<" "<<cha_f(a[x],rt[be[l+1]])<<endl;
del(a[x],rt[be[l+1]]);
ans^=shu[be[l+1]];
lastans=ans;
return;
}
if(x==r){
qu.erase(make_pair(l,r));
qu.insert(make_pair(l,r-1));
shu[be[l]]-=find(a[x],rt[be[l]]);
del(a[x],rt[be[l]]);
ans^=shu[be[l]];
lastans=ans;
return;
}
int L1=l,R1=x-1,L2=x+1,R2=r,len1=(R1-L1+1),len2=(R2-L2+1);
// cout<<"FAQ "<<L1<<" "<<R1<<" "<<L2<<" "<<R2<<" "<<shu[be[L1]]<<endl;
qu.erase(make_pair(l,r));
qu.insert(make_pair(L1,R1));
qu.insert(make_pair(L2,R2));
if(len1<len2){
be[L2]=be[L1];
for(int i=L1;i<=x;++i){
shu[be[L2]]-=find_f(a[i],rt[be[L2]]);
del(a[i],rt[be[L2]]);
}
nw++;be[L1]=nw;
for(int i=L1;i<=R1;++i){
insert(rt[be[L1]],a[i]);
shu[be[L1]]+=find(a[i],rt[be[L1]]);
}
}
else{
be[L2]=++nw;
for(int i=R2;i>=x;--i){
shu[be[L1]]-=find(a[i],rt[be[L1]]);
del(a[i],rt[be[L1]]);
}
for(int i=L2;i<=R2;++i){
insert(rt[be[L2]],a[i]);
shu[be[L2]]+=find(a[i],rt[be[L2]]);
}
}
// cout<<"FAQ "<<shu[be[L1]]<<" "<<shu[be[L2]]<<endl;
ans^=shu[be[L1]]^shu[be[L2]];
lastans=ans;
}
int main(){
// freopen("data.out","r",stdin);
// freopen("baibaide.out","w",stdout);
n=read();q=read();
for(int i=1;i<=n;++i){
a[i]=read();
for(int j=i;j<=n;j+=lowbit(j))add(root[j],1,MAXN,a[i],1);
}
// printf("%lld\n",tim);
nw=1;be[1]=nw;
for(int i=1;i<=n;++i){
insert(rt[nw],a[i]);
shu[nw]+=find(a[i],rt[nw]);
}
ans=shu[nw];qu.insert(make_pair(1,n));
while(q--){
int op=read();
LL x,y;
if(!op){
x=read(),y=read();
x=x^lastans,y=y^lastans;
solve_1(x,y);
}
else{
x=read();x=x^lastans;
solve_2(x);
}
printf("%lld\n",lastans);
}
//printf("%lld\n",tim);
return 0;
}
/*
4 2
4 3 2 1
0 2 5
1 4
*/