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

先看一道例题:传送门

题目大意:

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

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

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

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

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

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

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

有图为证:

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

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

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

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

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

更新操作:

void updata(int l,int r,int &x,int y,long long v)
{
T[++cnt]=T[y];x=cnt;//将当前版本与历史版本链接
if(l==r){
T[x].sum+=v;
T[x].tot++;
return ;
}
int mid=l+r>>;
if(mid>=v)updata(l,mid,T[x].l,T[y].l,v);//访问左节点
else updata(mid+,r,T[x].r,T[y].r,v);//访问右节点
T[x].sum=T[T[x].l].sum+T[T[x].r].sum;
T[x].tot=T[T[x].l].tot+T[T[x].r].tot;
}

查询和:

long long Qsum(int l,int r,int x,int y,int ql,int qr)
{
if(ql<=l&&qr>=r){
return T[y].sum-T[x].sum;
}//在查询区间内
int mid=l+r>>;
long long ans=;
if(mid>=ql)ans+=Qsum(l,mid,T[x].l,T[y].l,ql,qr);
if(mid<qr) ans+=Qsum(mid+,r,T[x].r,T[y].r,ql,qr);
return ans;
}

查询区间内有多少数:

long long Qcnt(int l,int r,int x,int y,int ql,int qr)
{
if(ql<=l&&qr>=r){
return T[y].tot-T[x].tot;
}//在查询区间内
int mid=l+r>>;
long long ans=;
if(mid>=ql)ans+=Qcnt(l,mid,T[x].l,T[y].l,ql,qr);
if(mid<qr) ans+=Qcnt(mid+,r,T[x].r,T[y].r,ql,qr);
return ans;
}

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

#include <cstdio>
#include <algorithm>
using namespace std; char tc()
{
static char tr[],*A=tr,*B=tr;
return A==B&&(B=(A=tr)+fread(tr,,,stdin),A==B)?EOF:*A++;
} int read()
{
char c;while(c=tc(),c<''||c>'');
int x=c-'';while(c=tc(),c>=''&&c<='')x=(x<<)+(x<<)+c-'';
return x;
} const int MAXN=*1e5;
long long N,Q,seed,a[MAXN+],sum[MAXN+],P[][];
long long nxt[MAXN+];
struct node{
int l,r;
long long sum,tot;
}T[MAXN*];
int root[MAXN+],cnt; void updata(int l,int r,int &x,int y,long long v)
{
T[++cnt]=T[y];x=cnt;
if(l==r){
T[x].sum+=v;
T[x].tot++;
return ;
}
int mid=l+r>>;
if(mid>=v)updata(l,mid,T[x].l,T[y].l,v);
else updata(mid+,r,T[x].r,T[y].r,v);
T[x].sum=T[T[x].l].sum+T[T[x].r].sum;
T[x].tot=T[T[x].l].tot+T[T[x].r].tot;
} long long Qsum(int l,int r,int x,int y,int ql,int qr)
{
if(ql<=l&&qr>=r){
return T[y].sum-T[x].sum;
}
int mid=l+r>>;
long long ans=;
if(mid>=ql)ans+=Qsum(l,mid,T[x].l,T[y].l,ql,qr);
if(mid<qr) ans+=Qsum(mid+,r,T[x].r,T[y].r,ql,qr);
return ans;
} long long Qcnt(int l,int r,int x,int y,int ql,int qr)
{
if(ql<=l&&qr>=r){
return T[y].tot-T[x].tot;
}
int mid=l+r>>;
long long ans=;
if(mid>=ql)ans+=Qcnt(l,mid,T[x].l,T[y].l,ql,qr);
if(mid<qr) ans+=Qcnt(mid+,r,T[x].r,T[y].r,ql,qr);
return ans;
} int buf[];
void printf(long long x)
{
buf[]=;
while(x)
buf[++buf[]]=x%,x/=;
if(!buf[])buf[]=,buf[]=;
while(buf[])
putchar(buf[buf[]--]+'');
} int main()
{
// freopen("HJT.txt","r",stdin);
// freopen("W.txt","w",stdout);
N=read();seed=read();
register int i,j;
for(i=;i<=N;i++)a[i]=read(),sum[i]=sum[i-]^a[i];
for(i=;i<=;i++)P[i][]=P[i][]=N+;
for(i=N;i>;i--){
nxt[i]=N+;
for(j=;j>-;j--)
nxt[i]=min(nxt[i],P[j][(sum[i-]>>j&)^]);
nxt[i]--;
for(j=;j>-;j--)
if((sum[i-]>>j&)^(sum[i]>>j&))
{P[j][(sum[i]>>j&)^]=i;break;}
}
/*for(int i=1;i<=N;i++){
for(int j=i+1;j<=N;j++){
if((sum[j]^sum[i-1])<(sum[j-1]^sum[i-1])){
nxt[i]=j-1;
break;
}
}
if(!nxt[i])nxt[i]=N;
}*/
for(i=;i<=N;i++)
updata(,N,root[i],root[i-],nxt[i]);
Q=read();
long long ans=,Qs,Qc,x,y;
for(i=Q;i;i--){
x=read(),y=read();
x=(x+ans*seed)%N+,y=(y+ans*seed)%N+;
if(x>y)swap(x,y);
ans=;
Qs=Qsum(,N,root[x-],root[y],x,y);
Qc=Qcnt(,N,root[x-],root[y],y+,N)*y;
ans=Qs+Qc+(y-x+)-(x+y)*(y-x+)/;
printf(ans);putchar('\n');
/* for(int j=x;j<=y;j++)
ans+=min(nxt[j],y)-j+1;
printf("%d\n",ans);*/
}
return ;
}

初识主席树_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. 浅谈SAP Cloud for Sales 自动化

    在Jerry还在本科进行计算机理论知识学习时,我曾经把软件开发里的质量工程师(Quality Engineer)理解成是每天只是简单地做着运行开发人员编写好的软件,如果发现问题,通知开发人员去修改这种 ...

  2. Redis 缓存穿透

    Redis 缓存穿透 https://www.cnblogs.com/jiekzou/p/9212114.html 场景描述:我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容 ...

  3. JavaScript中如何判断两变量是否“相等”?

    1 为什么要判断? 可能有些同学看到这个标题就会产生疑惑,为什么我们要判断JavaScript中的两个变量是否相等,JavaScript不是已经提供了双等号“==”以及三等号“===”给我们使用了吗? ...

  4. 如何使用Excel选择整列排序

    在excel中,排序的时候弹窗提示“若要执行此操作,所有合并单元格需大小相同”,该怎么操作才能实现排序呢?接下来,小编就和大家分享具体操作.   工具/原料   excel 方法/步骤     打开出 ...

  5. phonegap 的指南针 api Compass

    一. Compass 介绍方法参数   1.Compass 也就是,常说的指南针,又叫罗盘 2.方法 compass.getCurrentHeading compass.watchHeading co ...

  6. 【[SCOI2010]股票交易】

    感谢dzm,尽管接受了\(The \text{ }\text{ }king\text{ } \text{ }of\text{ } \text{ }SD\)的指点但我还是不会 至少方程还是比较好推的 状 ...

  7. 【转】Android之drawable state各个属性详解

    我们在定义一个drawable的时候可以通过xml定义的drawable对象.它使得一个图片能在不同的状态下显示不同的图案,比如一个Button,它有pressed,focused,或者其它状态,通过 ...

  8. mac使用brew安装配置常见测试工具

    Homebrew 包管理工具可以让你安装和更新程序变得更方便,目前在 OS X 系统中最受欢迎的包管理工具是 Homebrew. 安装 在安装 Homebrew 之前,需要将 Xcode Comman ...

  9. 【题解】洛谷P1198 [JSOI2008] 最大数(线段树)

    洛谷P1198:https://www.luogu.org/problemnew/show/P1198 思路 一道水水的线段树 20分钟A掉 这道题只涉及到单点修改和区间查询 所以这道题甚至不用Laz ...

  10. UITableView控件Protocell的Identifier设置 注意事项

    1.  注意:如果想使用Subtitle类型的单元格,需在Storyboard中将Protocell设置为subtitle类型,且Protocell的identifier必须与ViewControll ...