题解 P5057 【[CQOI2006]简单题】
Hydra_Shouko · · 题解
分块题解
看题目,维护一个01序列,支持区间异或,单点查询,强制在线
看到这相信大家都知道了这道题是数据结构,这道题线段树,树状数组,分块都能AC
线段树
分块在更多场合有用 (指骗分场合)
与线段树相比,分块的pushdown操作就是完全暴力,但线段树的pushdown或者pushup往往需要观察题目性质,或是巧妙转换维护的数据来让答案可维护,从这点上来说,分块思维难度比线段树小
考试时面对看起来像数据结构题的东西,如果意识到正解很难写时间不够调不出来,打个分块耐心调块长才是明智之举
上代码
#include<bits/stdc++.h>
using namespace std ;
const int MAXN = 100010;
int n,m;
struct Block{
int l,r;
int tag;
}blo[1000];
int fab[MAXN],a[MAXN],sq,bctr;
void set_up(){
sq = sqrt(n);
bctr = n/sq;
if(n%sq) ++bctr;
for(int i=1;i<=n;i++)
fab[i] = (i-1)/sq+1;
for(int i=1;i<bctr;i++){
blo[i].l = (i-1) * sq + 1;
blo[i].r = i * sq;
}
blo[bctr].l = (bctr-1) * sq + 1;
blo[bctr].r = n;
}
void pushdown(int x){
for(int i=blo[x].l;i<=blo[x].r;i++)
a[i] ^= 1;
blo[x].tag = 0;
}
void change (int x,int y){
if(fab[x] == fab[y]){
if(blo[fab[x]].tag) pushdown(fab[x]);
for(int i=x;i<=y;i++)
a[i] ^= 1;
return;
}
if(blo[fab[x]].l != x){
if(blo[fab[x]].tag) pushdown(fab[x]);
for(int i=x;i<=blo[fab[x]].r;i++)
a[i] ^= 1;
}
else blo[fab[x]].tag ^= 1;
if(blo[fab[y]].r != y){
if(blo[fab[y]].tag) pushdown(fab[y]);
for(int i=blo[fab[y]].l;i<=y;i++)
a[i] ^= 1;
}
else blo[fab[y]].tag ^= 1;
for(int i=fab[x]+1;i<=fab[y]-1;i++)
blo[i].tag ^= 1;
return;
}
int ask(int x){
return a[x]^blo[fab[x]].tag;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
set_up();
for(int i=1;i<=m;i++){
int t,x,y;
cin>>t;
if(t == 1){
cin>>x>>y;
change(x,y);
}
if(t == 2){
cin>>x;
cout<<ask(x)<<endl;
}
}
return 0;
}