【bzoj1858】【Scoi2010】序列操作【位运算】【卡常大法好】
2015-03-10 21:08
344 查看
其实这道题用线段树神马的应该是可做的……
但是鉴于我跪烂的位运算水平……
我决定用位运算压常数水过去~~
(其实要是数据强的话我早就完了)
我一次又一次犯的,b错误耗费了我一下午的时间……
这就是蒟蒻啊- -
一开始不知怎么回事,命令总是读不进去- -
然后发现~0U<<(r+1)有的时候不总是好用。
这两条语句的输出结果一个是0,一个是4294967295……
所以为了避免这种悲催的情况,就把~0U<<<<(r+1)改成~0U<<<
呵呵。
但是鉴于我跪烂的位运算水平……
我决定用位运算压常数水过去~~
(其实要是数据强的话我早就完了)
我一次又一次犯的,b错误耗费了我一下午的时间……
这就是蒟蒻啊- -
一开始不知怎么回事,命令总是读不进去- -
然后发现~0U<<(r+1)有的时候不总是好用。
printf("%u\n",~0U<<32); int r=32; printf("%u\n",~0U<<r);
这两条语句的输出结果一个是0,一个是4294967295……
所以为了避免这种悲催的情况,就把~0U<<<<(r+1)改成~0U<<<
呵呵。
#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(); } }
相关文章推荐
- 【BZOJ 1858】 [Scoi2010]序列操作
- BZOJ 1858 [Scoi2010]序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 [线段树]
- 【BZOJ1858】[Scoi2010]序列操作【线段树】
- bzoj 1858: [Scoi2010]序列操作 线段树
- bzoj 1858: [Scoi2010]序列操作(线段树)
- bzoj1858 [Scoi2010]序列操作
- 【BZOJ1858】[Scoi2010]序列操作 线段树
- BZOJ 1858 SCOI 2010 序列操作
- bzoj 1858: [Scoi2010]序列操作
- bzoj1858: [Scoi2010]序列操作
- bzoj1858: [Scoi2010]序列操作
- bzoj 1858: [Scoi2010] 序列操作 题解
- [BZOJ 1858][Scoi2010]序列操作(线段树)
- BZOJ1858: [Scoi2010]序列操作
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
- [BZOJ1858] [Scoi2010]序列操作
- BZOJ1858: [Scoi2010]序列操作
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
- BZOJ 1858 SCOI2010 序列操作 线段树