其实这道题用线段树神马的应该是可做的……
但是鉴于我跪烂的位运算水平……
我决定用位运算压常数水过去~~
(其实要是数据强的话我早就完了)
我一次又一次犯的,b错误耗费了我一下午的时间……
这就是蒟蒻啊- -
一开始不知怎么回事,命令总是读不进去- -
然后发现~0U<<(r+1)有的时候不总是好用。
printf("%u\n",~0U<<32);
int r=32;
printf("%u\n",~0U<<r);
这两条语句的输出结果一个是0,一个是4294967295……
所以为了避免这种悲催的情况,就把~0U
<<
<script type="math/tex" id="MathJax-Element-41"><<</script>(r+1)改成~0U
<<
<script type="math/tex" id="MathJax-Element-42"><<</script>r
<<
<script type="math/tex" id="MathJax-Element-43"><<</script>1。
呵呵。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef unsigned int uint;
struct bitset{
static const int maxlen=(100000>>5)+1;
static const uint inf=~0U;
uint d[maxlen];
int list[65536];
inline int cnt(uint x){
return list[x&0xFFFF]+list[x>>16];
}
void Not(int l,int r){
int l1=l>>5,r1=r>>5;
l&=31;r&=31;
d[l1]^=(1<<l)-1;
d[r1]^=inf<<r<<1;
for(;l1<=r1;++l1) d[l1]^=inf;
}
inline int count(int l,int r){
int ans=0;
int l1=l>>5,r1=r>>5;
l&=31,r&=31;
ans-=cnt(d[l1]&((1<<l)-1));
ans-=cnt(d[r1]>>r>>1);
for(;l1<=r1;++l1) ans+=cnt(d[l1]);
return ans;
}
void clear(int l,int r){
int l1=l>>5,r1=r>>5;
l&=31,r&=31;
if(l1==r1){d[l1]&=~((uint)(((1LL<<(r-l+1))-1)<<l));return;}
d[l1]&=(1<<l)-1;
d[r1]&=inf<<r<<1;
for(++l1;l1<r1;++l1) d[l1]=0;
}
void set(int l,int r){
int l1=l>>5,r1=r>>5;
l&=31,r&=31;
if(l1==r1){d[l1]|=(uint)(((1LL<<(r-l+1))-1)<<l);return;}
d[l1]|=inf<<l;
d[r1]|=(uint)((1LL<<r<<1)-1);
for(++l1;l1<r1;++l1) d[l1]=inf;
}
inline uint get(int pos){return (d[pos>>5]>>(pos&31))&1;}
}a;
inline int read(){
int x=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-48,ch=getchar();
return x;
}
int s[10];
void print(int x){
if(x) s[0]=0;
else s[0]=1,s[1]=0;
while(x) s[++s[0]]=x%10,x/=10;
while(s[0]) putchar(48+s[s[0]--]);
putchar('\n');
}
int main(){
for(int i=0;i<65536;++i) a.list[i]=a.list[i>>1]+(i&1);
int n=read(),m=read();
for(int i=0;i<n;++i)
a.d[i>>5]|=(read()<<(i&31));//i&31!!!!
while(m--){
int opt=read(),x=read(),y=read();
int ans,tmp;
switch(opt){
case 0:a.clear(x,y);break;
case 1:a.set(x,y);break;
case 2:a.Not(x,y);break;
case 3:print(a.count(x,y));break;
case 4:
ans=0;tmp=0;
for(int i=x;i<=y;++i){
if(a.get(i))tmp++;
else ans=max(ans,tmp),tmp=0;
}
print(max(ans,tmp));
break;
}
// a.print();
}
}