【Bitset】 BZOJ4810

难得学习一下C++的库。。【至今连map,vector都没用过的我。。

首先#include<bitset>或<bits/stdc++.h>

定义函数:  {

    bitset <15> b;    15是bitset长度 之后我就写成n了,b是变量名

    或:  string s='01001';  bitset <n> b(s);   若s不是01串会报错。若strlen(s)>n, bitset会只取s的前n位 否则 bitset会在前面补0   【注:举例n=10,    cout<<b 后得到的将是0000001001

    或:  bitset <n> b(5);   这里的5 是个unsigned long long,   bitset会将其转化成二进制,  若n小于其二进制位数,, 会保留低位的n个。

}

当然 也可以转回来{

    转unsigned:   unsigned int x=b.to_ulong();  printf("%u",x);    就是把bitset转成十进制,to_ulong()是个unsigned int;  b的位数大于32没有关系 但是b转成十进制的值大于等于1LL<<32(即爆unsigned)时 会报错。注意 这里若cout<<b是  0000001001 则x=9 ,所以右边是低位

    转string:   S=b.to_string(); S的strlen将和b的位数相同。
}

  {

    还是上面那个例子      cout<<b是  0000001001   则,最右边的1是  bitset的第0位 也就是低位,

      b.flip(2)  就是把第2位取反   cout:    0000001101 

      b.set(2)  就是把第2位 置为1    cout:    0000001101 

      b.reset(0)  就是把第0位 置为0    cout:    0000001000 

    如果 位置超过范围就会报错

  }

b[pos] 访问b中在pos处二进制位

而且位数相同的bitset之间可以用位运算 写法同整数位运算

 只要记住 bitset 在cout的时候 右边的是下标小的,下标i就表示二进制中2^i,其余就和整数理解一样了。

后面的拖别人的博客了:

  常用的成员函数:
b.any() b中是否存在置为1的二进制位?
b.none() b中不存在置为1的二进制位吗?
b.count() b中置为1的二进制位的个数
b.size() b中二进制位数的个数
b.test(pos) b中在pos处的二进制位置为1么?
b.set() 把b中所有二进制位都置为1
b.set(pos) 把b中在pos处的二进制位置为1
b.reset( ) 把b中所有二进制位都置为0
b.reset( pos ) 把b中在pos处的二进制位置置为0
b.flip( ) 把b中所有二进制位逐位取反
b.flip( pos ) 把b中在pos处的二进制位取反
b.to_ulong( ) 把b中同样的二进制位返回一个unsigned
os << b 把b中的位集输出到os流

 

还有一个:  如 bitset <3> a;  若a={110}   则a<<1 ={100} 即全体左移 多出来的那些补零。

 

那么现在就可以做这道题了。

就是莫队 然后 两个bitset互相&一下 就可以直接求答案了。。学bitset只是为了比手动压位方便一些、

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int O=315;
 4 const int X=100000;
 5 int f[100005],a[100005],n,m,x;
 6 struct opt{ int o,l,r,x,i; }op[100005];
 7 bitset <X+1> b,c,d,e;
 8 bool cmp(opt a,opt b){ if (a.l/O!=b.l/O) return a.l<b.l; else return a.r<b.r; }
 9 bool cmi(opt a,opt b){ return a.i<b.i; }
10 int main(){
11     scanf("%d%d",&n,&m);
12     for (int i=1;i<=n;++i) scanf("%d",&a[i]);
13     for (int i=1;i<=m;++i) scanf("%d%d%d%d",&op[i].o,&op[i].l,&op[i].r,&op[i].x),op[i].i=i;
14     sort(op+1,op+m+1,cmp); op[0].l=-O;
15     for (int i=1;i<=m;++i){
16         if (op[i].l/O==op[i-1].l/O){
17             for (int j=op[i-1].l;j<op[i].l;++j) {--f[a[j]]; if (!f[a[j]]) b.reset(a[j]),c.reset(X-a[j]);}
18             for (int j=op[i-1].l-1;j>=op[i].l;--j) {if (!f[a[j]]) b.set(a[j]),c.set(X-a[j]); ++f[a[j]];}
19             for (int j=op[i-1].r+1;j<=op[i].r;++j) {if (!f[a[j]]) b.set(a[j]),c.set(X-a[j]); ++f[a[j]];}
20         }else{
21             for (int j=op[i-1].l;j<=op[i-1].r;++j) {f[a[j]]=0; b.reset(a[j]); c.reset(X-a[j]);}
22             for (int j=op[i].l;j<=op[i].r;++j) {if (!f[a[j]]) b.set(a[j]),c.set(X-a[j]); ++f[a[j]];}
23         }
24         x=op[i].x;
25         if (op[i].o==1){
26             d=b>>x; d&=b;
27             op[i].x=d.any();
28         }else
29         if (op[i].o==2){
30             e=c<<(x+1>>1)>>(X-x+(x+1>>1));
31             d=b<<(X-x/2)>>(X-x/2); d&=e;   //<<X-r>>X-r+l
32             op[i].x=d.any();
33         }else{
34             x=0;
35             for (int j=1,s=floor(sqrt(op[i].x));j<=s;++j)
36             if (!(op[i].x%j)&&f[j]&&f[op[i].x/j]) {x=1; break;}
37             op[i].x=x;
38         }
39     }
40     sort(op+1,op+m+1,cmi);
41     for (int i=1;i<=m;++i) op[i].x?puts("yuno"):puts("yumi");
42     return 0;
43 }
citing

 

posted @ 2017-04-05 15:09  cyz666  阅读(289)  评论(0编辑  收藏  举报