• 如果没有撤销操作的话,它无非就是单纯的线段树。
• 如果加上撤销操作的话,它还可以是单纯的线段树。
• 把撤销操作看做是另一维的限制,那么修改与其对应的撤销就可以当做一个二维
的修改。
• 将询问的点取出来后建一棵 K-D tree 就可以当做线段树操作了。
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define ls son[u][0] 4 #define rs son[u][1] 5 #define p 998244353 6 using namespace std; 7 int n,m,root,K; 8 ll tmp; 9 ll sum[200050]; 10 ll add[200050]; 11 ll mul[200050]; 12 int t[200050],top; 13 int opt,x[2],y[2]; 14 int L[200050][2]; 15 int R[200050][2]; 16 int val[200050][2]; 17 int son[200050][2]; 18 struct node 19 { 20 int opt,l,r,end; 21 ll val; 22 }num[200050]; 23 bool cmp(int a,int b) 24 { 25 return val[a][K]<val[b][K]; 26 } 27 void pushup(int u) 28 { 29 add[u]=0; mul[u]=1; 30 for(int i=0;i<=1;++i) 31 { 32 L[u][i]=min(val[u][i],min(L[ls][i],L[rs][i])); 33 R[u][i]=max(val[u][i],max(R[ls][i],R[rs][i])); 34 } 35 } 36 void build(int &u,int l,int r,int k) 37 { 38 if(l>r) return ; 39 int mid=(l+r)>>1; K=k; 40 sort(t+l,t+r+1,cmp); 41 u=t[mid]; 42 build(ls,l,mid-1,k^1); 43 build(rs,mid+1,r,k^1); 44 pushup(u); 45 } 46 void pushdown(int u) 47 { 48 if(mul[u]!=1) 49 { 50 (sum[ls]*=mul[u])%=p; 51 (sum[rs]*=mul[u])%=p; 52 (mul[ls]*=mul[u])%=p; 53 (mul[rs]*=mul[u])%=p; 54 (add[ls]*=mul[u])%=p; 55 (add[rs]*=mul[u])%=p; 56 mul[u]=1; 57 } 58 if(add[u]!=0) 59 { 60 (sum[ls]+=add[u])%=p; 61 (sum[rs]+=add[u])%=p; 62 (add[ls]+=add[u])%=p; 63 (add[rs]+=add[u])%=p; 64 add[u]=0; 65 } 66 } 67 bool flagALL; 68 bool flagALO; 69 bool flagBIT; 70 void check(int u) 71 { 72 flagALL=flagALO=flagBIT=true; 73 for(int i=0;i<=1;++i) 74 if(x[i]>L[u][i]||R[u][i]>y[i]) 75 { 76 flagALL=false; 77 if(x[i]>val[u][i]||val[u][i]>y[i]) 78 { 79 flagALO=false; 80 if(x[i]>R[u][i]||y[i]<L[u][i]) 81 flagBIT=false; 82 } 83 } 84 } 85 void calc_add(int u) 86 { 87 if(!u) return ; 88 check(u); 89 if(!flagBIT) 90 return ; 91 if(flagALO) 92 { 93 if(opt==1) 94 (sum[u]+=tmp)%=p; 95 else 96 (sum[u]*=tmp)%=p; 97 } 98 if(flagALL) 99 { 100 if(opt==1) 101 (add[u]+=tmp)%=p; 102 else 103 { 104 (add[u]*=tmp)%=p; 105 (mul[u]*=tmp)%=p; 106 } 107 return ; 108 } 109 pushdown(u); 110 calc_add(ls); 111 calc_add(rs); 112 } 113 void calc_ask(int u,int v) 114 { 115 if(!u) return ; 116 if(val[v][0]<L[u][0]||val[v][0]>R[u][0]||val[v][1]<L[u][1]||val[v][1]>R[u][1]) 117 return ; 118 if(u==v) 119 { 120 printf("%lld ",sum[u]); 121 return ; 122 } 123 pushdown(u); 124 calc_ask(ls,v); 125 calc_ask(rs,v); 126 } 127 int main() 128 { 129 //freopen("ts.in","r",stdin); 130 //freopen("ts.out","w",stdout); 131 scanf("%d%d",&n,&m); 132 L[0][0]=200000; R[0][0]=0; 133 L[0][1]=200000; R[0][1]=0; 134 for(int i=1;i<=m;++i) 135 { 136 scanf("%d",&num[i].opt); 137 if(num[i].opt<=2) 138 { 139 scanf("%d%d%lld",&num[i].l,&num[i].r,&num[i].val); 140 num[i].end=m; 141 } 142 else if(num[i].opt==3) 143 { 144 scanf("%d",&val[i][1]); 145 val[i][0]=i; ++top; 146 t[top]=i; mul[i]=1; 147 } 148 else 149 { 150 scanf("%d",&num[i].end); 151 num[num[i].end].end=i; 152 } 153 } 154 build(root,1,top,0); 155 for(int i=1;i<=m;++i) 156 if(num[i].opt<=2) 157 { 158 opt=num[i].opt; 159 tmp=num[i].val; 160 tmp%=p; 161 x[0]=i; x[1]=num[i].l; 162 y[0]=num[i].end; y[1]=num[i].r; 163 calc_add(root); 164 } 165 else if(num[i].opt==3) 166 calc_ask(root,i); 167 return 0; 168 }