P4883 mzf的考验

题目背景

\(mzf\)立志要成为一个豪杰,当然,他也是一个\(OIer\)。 他希望自己除了会\(OI\)之外还会各种东西,比如心理学、吉他、把妹等等。 为了让自己有更大的魅力,他不驼背,不熬夜,整天锻炼,双目炯炯有神,是我们机房最不像\(OIer\)的人。 然而,在与我们格格不入若干天并且将《易经》研究透彻之后,承受不住我们对他另类的言论,他爆发了。 机房在那一刹那仿佛天塌地陷,世界末日。

题目描述

八卦有乾、坤、震、巽、坎、离、艮、兑; 两两组合,一上一下,形成了六十四卦,每卦六爻,一共三百八十四爻。 爻分阴阳,阳爻性属阳刚,阴爻性属阴柔。天下之大,无奇不有。千奇百怪,皆出此处。 \(mzf\)研究透彻了易经之后,画出了\(n\)个奇怪的图案。他说那是他改进出来的更强大的卜卦体系。 每一个图案有二十行,每一行要么是阴爻\((0)\),要么是阳爻\((1)\),作为一个\(OIer\),我们可以将卦象看成一个个二进制串; 他将\(n\)个图案画在了符纸上,然后进行\(m\)次操作:

操作1:翻转区间\([l,r]\)的图案,比如\((3,1,2,5)\)变成\((5,2,1,3)\);

操作2:\(mzf\)画地为卦,将\([l,r]\)之间的卦象都异或上新画的那个卦象;

操作3:\(mzf\)会询问机房里的其他人\([l,r]\)之间卦象代表的二进制数权值和。

如果不能正确回答每个操作\(3\),那么机房风水格局将会改变,我们都将...!

由于\(mzf\)疯狂之下将我们都捆♂绑♂了起来,所以只能求求你来帮我们解决这个问题。

输入输出格式

输入格式:

第一行两个正整数:\(n\),\(m\)(\(n\)为序列长度,\(m\)为操作个数)

第二行\(n\)个正整数:\(a[i]\) (用\(10\)进制数表示每个卦象)(\(1<=i<=n\))

接下来\(m\)行:每行首先一个正整数\(opt\)表示操作类型

\(opt==1\):两个正整数:\(l\),\(r\)。请翻转区间\([l,r]\);

\(opt==2\):三个正整数:\(l\),\(r\),\(d\)。请将区间\([l,r]\)中的所有卦象都异或卦象\(d\)。(\(0<=d<=10^5\))

\(opt==3\):两个正整数:\(l\),\(r\)。请查询区间\([l,r]\)的卦象权值和。

输出格式:

对于每个 \(opt==3\) 的情况,输出一行答案。

说明

对于\(20\%\)的数据,\(n<=1000\),\(m<=1000\)

对于另外\(20\%\)的数据,不存在操作\(1\)

对于另外\(20\%\)的数据,保证\(n\)为\(2\)的次幂,且在操作\(1\)中,保证\(l=i\times(2^j)+1,r=(i+1)\times(2^j)\),其中\(i\),\(j\)为任意值

对于\(100\%\)的数据,\(n<=10^5\),\(m<=5\times 10^4\),\(1<=l<=r<=n\),\(0<=d<2^{20}\)


发现,区间翻转要用平衡树,区间异或要用线段树打标记

平衡树不能打标记的原因是不能快速更新子树答案

我们可以把每一位拆开,然后对每一位维护区间1的个数,就可以快速更新子树答案啦

复杂度:\(O(mlogdlogn)\)


Code:

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #define ls ch[now][0]
  4. #define rs ch[now][1]
  5. #define ll long long
  6. const int N=1e5+10;
  7. int ch[N][2],dxor[N],siz[N],val[N],tag[N],tmp,root;
  8. int n,m,a[N];
  9. ll sum[N][21],dat[N][21],pow[21];
  10. void Reverse(int now){tag[now]^=1,tmp=ls,ls=rs,rs=tmp;}
  11. void updata(int now)
  12. {
  13. for(int i=0;i<=20;i++)
  14. sum[now][i]=sum[ls][i]+sum[rs][i]+dat[now][i];
  15. siz[now]=siz[ls]+siz[rs]+1;
  16. }
  17. void eor(int now,int x)
  18. {
  19. for(int i=0;i<=20;i++)
  20. if(x>>i&1)
  21. {
  22. sum[now][i]=1ll*siz[now]-sum[now][i];
  23. dat[now][i]^=1;
  24. }
  25. dxor[now]^=x;
  26. }
  27. void pushdown(int now)
  28. {
  29. if(tag[now])
  30. {
  31. if(ls) Reverse(ls);
  32. if(rs) Reverse(rs);
  33. tag[now]^=1;
  34. }
  35. if(dxor[now])
  36. {
  37. if(ls) eor(ls,dxor[now]);
  38. if(rs) eor(rs,dxor[now]);
  39. dxor[now]=0;
  40. }
  41. }
  42. void split(int now,int k,int &x,int &y)
  43. {
  44. if(!now) {x=y=0;return;}
  45. pushdown(now);
  46. if(siz[ls]+1<=k)
  47. x=now,split(rs,k-siz[ls]-1,rs,y);
  48. else
  49. y=now,split(ls,k,x,ls);
  50. updata(now);
  51. }
  52. int Merge(int x,int y)
  53. {
  54. if(!x||!y) return x|y;
  55. pushdown(x),pushdown(y);
  56. if(val[x]<val[y])
  57. {
  58. ch[x][1]=Merge(ch[x][1],y);
  59. updata(x);
  60. return x;
  61. }
  62. else
  63. {
  64. ch[y][0]=Merge(x,ch[y][0]);
  65. updata(y);
  66. return y;
  67. }
  68. }
  69. void reverse(int l,int r)
  70. {
  71. int x,y,z;
  72. split(root,r,x,y);
  73. split(x,l-1,x,z);
  74. Reverse(z);
  75. root=Merge(x,Merge(z,y));
  76. }
  77. void segdxor(int l,int r,int xo)
  78. {
  79. int x,y,z;
  80. split(root,r,x,y);
  81. split(x,l-1,x,z);
  82. eor(z,xo);
  83. root=Merge(x,Merge(z,y));
  84. }
  85. ll query(int l,int r)
  86. {
  87. int x,y,z;ll s=0;
  88. split(root,r,x,y);
  89. split(x,l-1,x,z);
  90. for(int i=0;i<=20;i++)
  91. s+=sum[z][i]*pow[i];
  92. root=Merge(x,Merge(z,y));
  93. return s;
  94. }
  95. int build(int l,int r,int pre)
  96. {
  97. if(l>r) return 0;
  98. if(l==r)
  99. {
  100. val[l]=pre+rand();
  101. for(int i=0;i<=20;i++)
  102. sum[l][i]=dat[l][i]=1ll*(a[l]>>i&1);
  103. siz[l]=1;
  104. return l;
  105. }
  106. int now=rand()%(r+1-l)+l;
  107. val[now]=pre+rand();
  108. for(int i=0;i<=20;i++)
  109. dat[now][i]=1ll*(a[now]>>i&1);
  110. ls=build(l,now-1,val[now]);
  111. rs=build(now+1,r,val[now]);
  112. updata(now);
  113. return now;
  114. }
  115. int main()
  116. {
  117. scanf("%d%d",&n,&m);
  118. for(int i=1;i<=n;i++) scanf("%d",a+i);
  119. for(int i=0;i<=20;i++) pow[i]=1ll<<i;
  120. root=build(1,n,0);
  121. for(int op,l,r,d,i=1;i<=m;i++)
  122. {
  123. scanf("%d%d%d",&op,&l,&r);
  124. if(op==1) reverse(l,r);
  125. else if(op==2)
  126. {
  127. scanf("%d",&d);
  128. segdxor(l,r,d);
  129. }
  130. else
  131. printf("%lld\n",query(l,r));
  132. }
  133. return 0;
  134. }

2018.9.9

洛谷 P4883 mzf的考验 解题报告的更多相关文章

  1. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  2. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  3. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  4. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

  5. 洛谷1303 A*B Problem 解题报告

    洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...

  6. 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告

    [USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...

  7. 洛谷 P1379 八数码难题 解题报告

    P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...

  8. NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告

    前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...

  9. 洛谷 P1129 [ZJOI2007]矩阵游戏 解题报告

    P1129 [ZJOI2007]矩阵游戏 题目描述 小\(Q\)是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏.矩阵游戏在一个\(N*N\)黑白方阵进行(如同国际象棋一般 ...

随机推荐

  1. 用h+c实现天天生鲜首页

    网页效果图:http://www.dycun.cc/ 如下: css代码 main.css: /*因为大部分的字体都是12px,颜色一致, 所以统一设置下*/ body{ font-size: 12p ...

  2. [转] vim配置python自动补全

    vim python自动补全插件:pydiction 可以实现下面python代码的自动补全: 1.简单python关键词补全 2.python 函数补全带括号 3.python 模块补全 4.pyt ...

  3. No module named 'PyQt5.sip'

    使用pyinstaller打包python文件为windows可执行程序可能遇到的问题 pyinstaller yourprogram.py打包的程序双击打开一闪而过,提示上面标题的错误 把pycom ...

  4. linux最大进程数

    使用 ulimit -a 命令,查看 max user processes 的输出,就是系统最大进程数 core file size (blocks, -c) unlimited data seg s ...

  5. POJ 3662 (二分+SPFA

    Telephone Lines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8856   Accepted: 3211 D ...

  6. 笔记-python lib-pymongo

    笔记-python lib-pymongo 1.      开始 pymongo是python版的连接库,最新版为3.7.2. 文档地址:https://pypi.org/project/pymong ...

  7. dfs序线段树

    dfs序+线段树,啥?如果在一棵树上,需要你修改一些节点和查询一些节点,如果直接dfs搜的话肯定超时,那用线段树?树结构不是区间啊,怎么用?用dfs序将树结构转化为一个区间,就能用线段树进行维护了. ...

  8. 【02】webstorm配置babel转换器+截图(by魔芋)

    [02]webstorm配置babel转换器+截图(by魔芋)   [02]魔芋的安装过程     01,配置babel.   02,用webstorm.注意webstorm的版本号.   03,使用 ...

  9. Java学习笔记23---内部类之局部内部类只能访问final的局部变量

    局部内部类是定义在方法体或代码块中的类,在笔记19中已有过简单介绍. 今天要讨论的是局部内部类为什么只能访问为常量的局部变量. 作者: 博客园--蝉蝉 请尊重作者劳动成果,转载请在标题注明“转载”字样 ...

  10. JavaSE总结--多线程

    进程: 进程之间内存隔离,内存不共享. 线程: 可以共享内存. 每个线程都是一个栈. 多线程的好处: 1)防止程序阻塞. wait与notify的区别: 针对等待队列而言. wait:进入等待队列.必 ...