主席树刚接触觉得超强,根本看不懂,看了几位dalao的代码后终于理解了主席树。

先看一道例题:传送门

题目大意:

假设我们预处理出了每个数满足条件的最右边界。

先考虑暴力做法,直接对x~y区间暴枚,求出答案。

主席树做法:设主席树的下标表示边界为i的信息。

网上找不到百度百科对主席树的定义,那我说说自己的理解。

主席树是一棵可持久化线段树,可以找出线段树的历史版本。

主席树的空间复杂度可以达到O((N+M)logN)(无修改的情况下)。

因为每一次修改至多修改logN个点。

有图为证:

对于这道题,主席树维护的是边界为i的总和和总共有几个这样的点。

注意这里主席树的下标(i)是这个版本边界这个数为i。

主席树建树其实是对前缀1~i的建树。

因为你之前1~i-1建过树,你建的1~i版本是在1~i-1版本的基础上建立的。

边界就是你之前预处理出来的边界。

更新操作:

  1. void updata(int l,int r,int &x,int y,long long v)
  2. {
  3. T[++cnt]=T[y];x=cnt;//将当前版本与历史版本链接
  4. if(l==r){
  5. T[x].sum+=v;
  6. T[x].tot++;
  7. return ;
  8. }
  9. int mid=l+r>>;
  10. if(mid>=v)updata(l,mid,T[x].l,T[y].l,v);//访问左节点
  11. else updata(mid+,r,T[x].r,T[y].r,v);//访问右节点
  12. T[x].sum=T[T[x].l].sum+T[T[x].r].sum;
  13. T[x].tot=T[T[x].l].tot+T[T[x].r].tot;
  14. }

查询和:

  1. long long Qsum(int l,int r,int x,int y,int ql,int qr)
  2. {
  3. if(ql<=l&&qr>=r){
  4. return T[y].sum-T[x].sum;
  5. }//在查询区间内
  6. int mid=l+r>>;
  7. long long ans=;
  8. if(mid>=ql)ans+=Qsum(l,mid,T[x].l,T[y].l,ql,qr);
  9. if(mid<qr) ans+=Qsum(mid+,r,T[x].r,T[y].r,ql,qr);
  10. return ans;
  11. }

查询区间内有多少数:

  1. long long Qcnt(int l,int r,int x,int y,int ql,int qr)
  2. {
  3. if(ql<=l&&qr>=r){
  4. return T[y].tot-T[x].tot;
  5. }//在查询区间内
  6. int mid=l+r>>;
  7. long long ans=;
  8. if(mid>=ql)ans+=Qcnt(l,mid,T[x].l,T[y].l,ql,qr);
  9. if(mid<qr) ans+=Qcnt(mid+,r,T[x].r,T[y].r,ql,qr);
  10. return ans;
  11. }

All code:(被注释的部分是暴力代码)

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4.  
  5. char tc()
  6. {
  7. static char tr[],*A=tr,*B=tr;
  8. return A==B&&(B=(A=tr)+fread(tr,,,stdin),A==B)?EOF:*A++;
  9. }
  10.  
  11. int read()
  12. {
  13. char c;while(c=tc(),c<''||c>'');
  14. int x=c-'';while(c=tc(),c>=''&&c<='')x=(x<<)+(x<<)+c-'';
  15. return x;
  16. }
  17.  
  18. const int MAXN=*1e5;
  19. long long N,Q,seed,a[MAXN+],sum[MAXN+],P[][];
  20. long long nxt[MAXN+];
  21. struct node{
  22. int l,r;
  23. long long sum,tot;
  24. }T[MAXN*];
  25. int root[MAXN+],cnt;
  26.  
  27. void updata(int l,int r,int &x,int y,long long v)
  28. {
  29. T[++cnt]=T[y];x=cnt;
  30. if(l==r){
  31. T[x].sum+=v;
  32. T[x].tot++;
  33. return ;
  34. }
  35. int mid=l+r>>;
  36. if(mid>=v)updata(l,mid,T[x].l,T[y].l,v);
  37. else updata(mid+,r,T[x].r,T[y].r,v);
  38. T[x].sum=T[T[x].l].sum+T[T[x].r].sum;
  39. T[x].tot=T[T[x].l].tot+T[T[x].r].tot;
  40. }
  41.  
  42. long long Qsum(int l,int r,int x,int y,int ql,int qr)
  43. {
  44. if(ql<=l&&qr>=r){
  45. return T[y].sum-T[x].sum;
  46. }
  47. int mid=l+r>>;
  48. long long ans=;
  49. if(mid>=ql)ans+=Qsum(l,mid,T[x].l,T[y].l,ql,qr);
  50. if(mid<qr) ans+=Qsum(mid+,r,T[x].r,T[y].r,ql,qr);
  51. return ans;
  52. }
  53.  
  54. long long Qcnt(int l,int r,int x,int y,int ql,int qr)
  55. {
  56. if(ql<=l&&qr>=r){
  57. return T[y].tot-T[x].tot;
  58. }
  59. int mid=l+r>>;
  60. long long ans=;
  61. if(mid>=ql)ans+=Qcnt(l,mid,T[x].l,T[y].l,ql,qr);
  62. if(mid<qr) ans+=Qcnt(mid+,r,T[x].r,T[y].r,ql,qr);
  63. return ans;
  64. }
  65.  
  66. int buf[];
  67. void printf(long long x)
  68. {
  69. buf[]=;
  70. while(x)
  71. buf[++buf[]]=x%,x/=;
  72. if(!buf[])buf[]=,buf[]=;
  73. while(buf[])
  74. putchar(buf[buf[]--]+'');
  75. }
  76.  
  77. int main()
  78. {
  79. // freopen("HJT.txt","r",stdin);
  80. // freopen("W.txt","w",stdout);
  81. N=read();seed=read();
  82. register int i,j;
  83. for(i=;i<=N;i++)a[i]=read(),sum[i]=sum[i-]^a[i];
  84. for(i=;i<=;i++)P[i][]=P[i][]=N+;
  85. for(i=N;i>;i--){
  86. nxt[i]=N+;
  87. for(j=;j>-;j--)
  88. nxt[i]=min(nxt[i],P[j][(sum[i-]>>j&)^]);
  89. nxt[i]--;
  90. for(j=;j>-;j--)
  91. if((sum[i-]>>j&)^(sum[i]>>j&))
  92. {P[j][(sum[i]>>j&)^]=i;break;}
  93. }
  94. /*for(int i=1;i<=N;i++){
  95. for(int j=i+1;j<=N;j++){
  96. if((sum[j]^sum[i-1])<(sum[j-1]^sum[i-1])){
  97. nxt[i]=j-1;
  98. break;
  99. }
  100. }
  101. if(!nxt[i])nxt[i]=N;
  102. }*/
  103. for(i=;i<=N;i++)
  104. updata(,N,root[i],root[i-],nxt[i]);
  105. Q=read();
  106. long long ans=,Qs,Qc,x,y;
  107. for(i=Q;i;i--){
  108. x=read(),y=read();
  109. x=(x+ans*seed)%N+,y=(y+ans*seed)%N+;
  110. if(x>y)swap(x,y);
  111. ans=;
  112. Qs=Qsum(,N,root[x-],root[y],x,y);
  113. Qc=Qcnt(,N,root[x-],root[y],y+,N)*y;
  114. ans=Qs+Qc+(y-x+)-(x+y)*(y-x+)/;
  115. printf(ans);putchar('\n');
  116. /* for(int j=x;j<=y;j++)
  117. ans+=min(nxt[j],y)-j+1;
  118. printf("%d\n",ans);*/
  119. }
  120. return ;
  121. }

初识主席树_Prefix XOR的更多相关文章

  1. BZOJ5338[TJOI2018]xor——主席树+dfs序

    题目描述 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值vi. 现在有Q 次操作,操作如下: 1  x y    查询节点x的子树中与y异或结果的最大值 2 x y z     ...

  2. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  3. [bzoj2588][count on a tree] (主席树+lca)

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

  4. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1288  Solved: 490 ...

  5. 【BZOJ3123】森林(主席树,启发式合并)

    题意:一个带点权的森林,要求维护以下操作: 1.询问路径上的点权K大值 2.两点之间连边 n,m<=80000 思路:如果树的结构不发生变化只需要维护DFS序 现在因为树的结构发生变化,要将两棵 ...

  6. 【BZOJ-2588】Count on a tree 主席树 + 倍增

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 3749  Solved: 873[ ...

  7. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  8. BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

    2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...

  9. bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

    Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...

随机推荐

  1. 轻松bypass360网站卫士WAFSQL注入防护

    随便网上找了一个网站,只是测试一下,没有干非法的事情! code 区域 http://www.py-guanyun.com/CompHonorBig.asp?id=49 code 区域 http:// ...

  2. mongodb 创建auto increment 自增函数

    计数器表  > db.counters.insert({_id: "userid",seq: 0}  ); > db.counters.find();  { " ...

  3. sql 获取每个分组的前N条记录的写法

    SELECT * FROM ( --根据 tb表的name进行分组,根据年龄排序 SELECT * , ROW_NUMBER() OVER ( PARTITION BY name ORDER BY a ...

  4. Handler的简单使用介绍

    Handler在android程序开发中使用的非常频繁.我们知道android是不允许在子线程中更新UI的,这就需要借助Handler来实现,那么你是否想过为什么一定要这个这样子做呢?而且Handle ...

  5. Codeforces Round #533 (Div. 2) B. Zuhair and Strings 【模拟】

    传送门:http://codeforces.com/contest/1105/problem/B B. Zuhair and Strings time limit per test 1 second ...

  6. ssm小小整合

    ssm整合: 首先是创建数据库: CREATE TABLE `user` ( `id` ) NOT NULL, `username` varchar() NOT NULL, `password` va ...

  7. __future__模块

    Python提供了__future__模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中使用一些新版本的特性,比如除法: 在Python 2.x中,对于除法有两种情况,如果是整数相除 ...

  8. 面试准备——(二)专业知识(2)Python

    面试遇到的问题: 滴滴: 1. Python的数据结构 2. list和tuple的区别 3. list中有哪些操作?append和extend的区别? 4. list和dict的却别?dict是有序 ...

  9. window7及以上 创建软链接 mklink

    软链接是一种文件共享方式. 命令:mklink /d "C:\d" "C:\e" 有哪些坑: 1.此命名必须以管理员方式在cmd运行 2.文件必须不存在..通过 ...

  10. 【POJ 3368】Frequent values(RMQ)

    Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In ad ...