题解 P2574 【XOR的艺术】

SuperJvRuo

2018-10-04 15:33:11

Solution

就这沙雕题还用得上线段树/分块? 我们可以压位处理,将32个二进制位压入一个```unsigned int```中,暴力修改,开启O2即可AC。 ``` #include<cstdio> #include<cctype> #include<utility> #define PII pair<int,int> //以空间换时间,快速统计一个unsigned int中有多少个1 const unsigned char popcount_tab[]= { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8, }; //把数分成4段进行统计 int popcount (register unsigned int x) { return popcount_tab[(x>>0)&0xff]+popcount_tab[(x>>8)&0xff]+popcount_tab[(x>>16)&0xff]+popcount_tab[(x>>24)&0xff]; } int Read() { int x=0;char c=getchar(); while(!isdigit(c)) { c=getchar(); } while(isdigit(c)) { x=x*10+(c^48); c=getchar(); } return x; } using std::pair; unsigned int arr[10005]; //将序列下标转换为压位下标与位置 PII trans(int pos) { return PII(pos/32,pos%32); } //整个在一个数里的部分xor-1,零散部分挨个处理 void Rev(PII l,PII r) { if(l.first==r.first) for(int i=l.second;i<=r.second;++i) arr[l.first]^=(1<<i); else { for(int i=l.first+1;i!=r.first;++i) arr[i]^=-1; for(int i=l.second;i<32;++i) arr[l.first]^=(1<<i); for(int i=0;i<=r.second;++i) arr[r.first]^=(1<<i); } } //同上 int Query(PII l,PII r) { int res=0; if(l.first==r.first) for(int i=l.second;i<=r.second;++i) res+=(arr[l.first]>>i)&1; else { for(int i=l.first+1;i!=r.first;++i) res+=popcount(arr[i]); for(int i=l.second;i<32;++i) res+=(arr[l.first]>>i)&1; for(int i=0;i<=r.second;++i) res+=(arr[r.first]>>i)&1; } return res; } char str[200005]; int main() { int n=Read(),m=Read(),opt; scanf("%s",str+1); for(int i=1;i<=n;++i) { if(str[i]-'0'==1) { PII pos=trans(i); arr[pos.first]+=1<<pos.second; } } while(m--) { opt=Read(); PII l=trans(Read()); PII r=trans(Read()); if(opt==0) { Rev(l,r); } else { printf("%d\n",Query(l,r)); } } return 0; } ```