【JZOJ 4711】 Binary
2016-08-17 19:53
330 查看
Description
Analysis
对于这种有xor,and,or的题都有经典套路:拆位维护,计算。这题亦是如此。
若当前二进制位y=0,显然不用管。
然后呢?
正解是一个很劲的做法。
注意到x and 2i的值是循环出现的,2i−1个0和2i−1个2i−1交替出现。
那一个数x的第i−1位要为1,即x mod 2i∈[2i−1,2i−1]
所以开始把所有数的所有位置加入一个数据结构(BIT),维护第k−1位的∑ni=1ai mod 2k,修改操作直接每位修改,查询操作就在数据结构里查询该位有多少再上面那个区间里面的数,统计答案。
Code
#include<cstdio> #include<cmath> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; typedef long long ll; const int N=100010,M=22; int n,a ,tr[M][1<<M]; ll _2[M]; int lowbit(int x){return x&-x;} int query(int k,int x) { int t=0; for(x++;x;x-=lowbit(x)) t+=tr[k][x]; return t; } void change(int k,int x,int p) { for(x++;x<=_2[k+1];x+=lowbit(x)) tr[k][x]+=p; } int main() { _2[0]=1; fo(i,1,21) _2[i]=_2[i-1]*2; int op,x,y,_; scanf("%d %d",&n,&_); fo(i,1,n) { scanf("%d",&a[i]); fo(j,0,20) change(j,a[i]%_2[j+1],1); } ll ans; while(_--) { scanf("%d %d %d",&op,&x,&y); if(op==1) { fo(i,0,20) change(i,a[x]%_2[i+1],-1); a[x]=y; fo(i,0,20) change(i,a[x]%_2[i+1],1); } else { ans=0; fo(i,0,20) if(y&_2[i]) { ll t=0; int m=_2[i+1]; int l=((_2[i]-1-x)%m+m)%m,r=((m-1-x)%m+m)%m; if(l<=r) t=query(i,r)-query(i,l); else t=query(i,m)-query(i,l)+query(i,r); ans=ans+t*_2[i]; } printf("%lld\n",ans); } } return 0; }
相关文章推荐
- BSGS(a^x%p=b)
- 多个线程执行多个任务,解决该问题的死锁问题
- poj3264(线段树) Balanced Lineup
- file知识点总结,自己学的
- hadoop完全分布式
- Xcode 快捷键
- JavaWeb学习篇之----Servlet过滤器Filter和监听器
- 51nod oj 1099 任务执行顺序 【贪心】
- chapter2、操作系统简介
- 快速排序算法学习笔记
- 更好的Vim入门教程
- JZOJ4711. Binary
- UVa 1001 Say Cheese (Floyd)
- 02_分页_02_步步优化
- CodeForces 688A Opponents
- HDOJ-----1166敌兵布阵(树状数组)
- crtmpserver搭建 linux
- web.xml加载顺序
- 使用jdk1.5的多线程 lock condition 实现方式实现 生产者消费者问题
- UVALive 7461 Separating Pebbles (计算几何)