[2017雅礼7-6]right 分块
来源:互联网 发布:什么是creis中指数据 编辑:程序博客网 时间:2024/06/06 03:35
稍加分(da)析(biao)可知,当p为奇数时,SG(x)=x&1,当p为偶数时,SG(x)=(x%(p+1)==p)?2:((x%(p+1))&1)。
奇数的话相当于区间翻转,区间异或和,直接线段树即可。
偶数的话分块来处理,每个块维护一个add标记和两个有序数组,分别表示奇余数和偶余数,区间加的时候整块的打标记,零散的直接重构,时间复杂度O(n/s+slogs)。查询的时候整块lower_bound找有多少个1和2,1的话应该是奇数数组中还没+add不超过p的,偶数数组中+p超过了add的,2的话根据add的奇偶性来决定在哪个数组查询,零散的也直接重构,时间复杂度O(nlogs/s+slogs)。
所以我也不知道s该取多少,大概250最优吧。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mod (p+1)using namespace std;const int maxn=100100;const int size=220;int n,p,q,a[maxn];inline int ID(int x) {return (x-1)/size+1;}inline int L(int x) {return (x-1)*size+1;}inline int R(int x) {return min(n,x*size);}struct tree{ tree *ls,*rs; int l,r,sum,rev; tree() { ls=rs=NULL; sum=rev=0; } void pushdown() { if(rev) { if((r-l+1)&1)sum^=1; rev=0; if(ls!=NULL)ls->rev^=1; if(rs!=NULL)rs->rev^=1; } } void update() { ls->pushdown(); rs->pushdown(); sum=ls->sum^rs->sum; } void build(int lx,int rx) { l=lx;r=rx; if(l==r) {sum=(a[l]&1);return ;} int mid=(l+r)>>1; (ls=new tree)->build(lx,mid); (rs=new tree)->build(mid+1,rx); update(); } void reverse(int lx,int rx) { if(l==lx&&r==rx) {rev^=1;return ;} pushdown(); int mid=(l+r)>>1; if(rx<=mid) ls->reverse(lx,rx); else if(lx>mid) rs->reverse(lx,rx); else {ls->reverse(lx,mid); rs->reverse(mid+1,rx);} update(); } int query(int lx,int rx) { pushdown(); if(l==lx&&r==rx){return sum;}; int mid=(l+r)>>1; if(rx<=mid) return ls->query(lx,rx); else if(lx>mid) return rs->query(lx,rx); else {return ls->query(lx,mid)^rs->query(mid+1,rx);} }}*xtr;struct block{ int add,rst[2][400],num[2],id; void init(int x) { memset(rst,0x3f3f3f3f,sizeof(rst)); add=num[0]=num[1]=0; id=x; } void build() { int temp=add; init(id); for(int i=L(id);i<=R(id);i++) { a[i]=(a[i]+temp)%mod; if(a[i]&1) rst[1][++num[1]]=a[i]; else rst[0][++num[0]]=a[i]; } sort(rst[1]+1,rst[1]+num[1]+1); sort(rst[0]+1,rst[0]+num[0]+1); } void modify(int x) { add=(add+x)%mod; } void bmodify(int l,int r,int x) { for(int i=l;i<=r;i++) a[i]=(a[i]+x)%mod; build(); } int query() { bool pd=(add&1); int re,lb,ub,lb0,lb1; lb0=lower_bound(rst[pd]+1,rst[pd]+num[pd]+2,p+1-add)-rst[pd]; lb1=lower_bound(rst[!pd]+1,rst[!pd]+num[!pd]+2,p+1-add)-rst[!pd]; re=((num[pd]-lb0+lb1)&1); //cout<<"re1:"<<re<<endl; lb=lower_bound(rst[pd]+1,rst[pd]+num[pd]+2,p-add)-rst[pd]; ub=lb0; re^=(((ub-lb)&1)<<1); //cout<<"re2:"<<re<<endl; return re; } int bquery(int l,int r) { int re=0; build(); for(int i=l;i<=r;i++) { if(a[i]==p) re^=2; if(a[i]&1) re^=1; } return re; }}blk[600];int main(){ freopen("right.in","r",stdin); freopen("right.out","w",stdout); scanf("%d%d%d",&n,&q,&p); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]%=(p+1); } if(p&1) (xtr=new tree)->build(1,n); else for(int i=1;i<=ID(n);i++) { blk[i].init(i); blk[i].build(); } while(q--) { int opt,l,r,x=0; scanf("%d%d%d",&opt,&l,&r); if(opt==0) { scanf("%d",&x); x%=mod; if(p&1) {if(x&1) xtr->reverse(l,r);} else { if(ID(l)==ID(r)) blk[ID(l)].bmodify(l,r,x); else { blk[ID(l)].bmodify(l,R(ID(l)),x); blk[ID(r)].bmodify(L(ID(r)),r,x); for(int i=ID(l)+1;i<=ID(r)-1;i++) blk[i].modify(x); } } } else { if(p&1) printf("%d\n",(xtr->query(l,r)!=0)); else { int ans=0; if(ID(l)==ID(r)) ans^=blk[ID(l)].bquery(l,r); else { ans^=blk[ID(l)].bquery(l,R(ID(l))); ans^=blk[ID(r)].bquery(L(ID(r)),r); for(int i=ID(l)+1;i<=ID(r)-1;i++) ans^=blk[i].query(); } printf("%d\n",(ans!=0)); } } } }
阅读全文
0 0
- [2017雅礼7-6]right 分块
- (7)分块矩阵
- 分块。。
- 分块
- 分块
- 分块
- 分块
- 分块
- 分块
- 【分块】
- IE 6/7 bug --- float:right
- [分块 随机Hash] Romanian IOI 2017 Selection #6 Jolteon
- [分块] [BZOJ2724] [Violet 6] 蒲公英
- bzoj2724 [Violet 6]蒲公英 分块
- right
- right
- ie 7 float right 换行
- [分块][哈希] [Romanian IOI 2017 Selection #6] Jolteon && [LOJ #6187] Odd
- 629. K Inverse Pairs Array
- [bzoj4919]大根堆
- hadoop环境配置在eclipse上配置的总结
- 【补充】位置无关码和位置有关码
- 使用putty远程登录Ubuntu时,报Network error:Connection refused错误及解决(记录)
- [2017雅礼7-6]right 分块
- mysql 插件式存储引擎
- 用mybatis取值,字段赋值错误的问题
- java提高篇(二五)-----HashTable
- easyui主页main.jsp
- 关于IntelliJ IDEA 文档无法编辑的解决办法
- LMS算法
- MAC使用注意事项
- POJ 3095 Linear Pachinko 笔记