题目分析:
对于一个$add$操作,它的特点是与树状数组的查询相同,会给$1$到它自己产生影响,而$query$操作则会途径所有包含它的树状数组点。现在$add$操作具有前向性(不会影响之后的点)。所以实际上这是求后缀和。
现在我们知道,对于$query(l,r)$,它等于${Xor}_{i=l-1}^{r-1}A[i]$。与原答案异或,得到$A[l-1] \oplus A[r]$,若它为$1$则假,否则为真。所以我们把它看作平面上的点,对于一个$add(l,r)$操作,会对右端点在其中的产生$\frac{1}{r-l+1}$的改变影响,对两端都在其中的产生$\frac{2}{r-l+1}$的改变影响,对左端点在其中的产生$\frac{1}{r-l+1}$的改变影响。标记合并不难。然后标记永久化一下就行了。
对于$l=1$的单独处理。
代码:
#include<bits/stdc++.h>
using namespace std; const int maxn = ; const int mod = ; int n,m,num=,xL,xR,yL,yR,ans;
struct qy{
int cas,l,r;
}Q[maxn]; struct node{
int ch[],root,data;
}T[maxn*]; int fast_pow(int now,int pw){
int res = ,bit = ,fun = now;
while(bit <= pw){
if(bit & pw) res = (1ll*res*fun)%mod;
fun = (1ll*fun*fun)%mod; bit<<=;
}
return res;
} int merge(int p1,int p2){return ((1ll*p1*(-p2)+1ll*p2*(-p1))%mod+mod)%mod;} void Query(int now,int tl,int tr,int l,int r){
int pls = T[now].root,ll = tl,rr = n;
while(true){
int mid = (ll+rr)/;
ans = merge(ans,(-T[pls].data+mod)%mod);
if(mid >= r){
if(!T[pls].ch[]) break;
else pls = T[pls].ch[];
rr = mid;
}else{
if(!T[pls].ch[]) break;
else pls = T[pls].ch[];
ll = mid+;
}
}
int mid = (tl+tr)/;
if(mid >= l){if(T[now].ch[])Query(T[now].ch[],tl,mid,l,r);}
else{if(T[now].ch[])Query(T[now].ch[],mid+,tr,l,r);}
} void M2(int now,int tl,int tr,int data){
if(tl >= yL && tr <= yR){
T[now].data = merge(T[now].data,data);
return;
}
int mid = (tl+tr)/;
if(!T[now].ch[] && !T[now].ch[]){
T[now].ch[] = ++num; T[now].ch[] = ++num;
T[num-].data = ; T[num].data = ;
}
if(mid >= yL) M2(T[now].ch[],tl,mid,data);
if(mid < yR) M2(T[now].ch[],mid+,tr,data);
} void Modify(int now,int tl,int tr,int data){
if(tl >= xL && tr <= xR){
M2(T[now].root,tl,n,data);
return;
}
int mid = (tl+tr)/;
if(mid >= xL){
if(T[now].ch[]==){
num++;T[now].ch[] = num;
num++;T[num-].root = num;T[num].data = ;
}
Modify(T[now].ch[],tl,mid,data);
}
if(mid < xR){
if(T[now].ch[]==){
num++;T[now].ch[] = num;
num++;T[num-].root = num;T[num].data = ;
}
Modify(T[now].ch[],mid+,tr,data);
}
} void read(){
T[].root = ; T[].data = ;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++) scanf("%d%d%d",&Q[i].cas,&Q[i].l,&Q[i].r);
} void work(){
int cnt = ;
for(int i=;i<=m;i++){
if(Q[i].cas == ){
cnt^=; xL = ,xR = Q[i].l-,yL = Q[i].l,yR = Q[i].r;
Modify(,,n,fast_pow(Q[i].r-Q[i].l+,mod-));
xL = Q[i].l,xR = Q[i].r,yL = Q[i].l,yR = Q[i].r;
Modify(,,n,*fast_pow(Q[i].r-Q[i].l+,mod-)%mod);
xL = Q[i].l,xR = Q[i].r,yL = Q[i].r+,yR = n;
Modify(,,n,fast_pow(Q[i].r-Q[i].l+,mod-));
}else{
ans = ; Query(,,n,Q[i].l-,Q[i].r);
if((Q[i].l == && (!cnt))||Q[i].l != ) printf("%d\n",ans);
else printf("%d\n",(-ans+mod)%mod);
}
}
} int main(){
read();
work();
return ;
}