【CF757G】Can Bash Save the Day?

题意:给你一棵n个点的树和一个排列${p_i}$,边有边权。有q个操作:

1 l r x:询问$\sum\limits_{i=l}^r dist(p_i,x)$
2 x:$swap(a_x,a_{x+1})$

$n,q\le 2\times 10^5$,强制在线。
题解:学到了新姿势:可持久化点分树。我们先将询问变成前缀相减的形式,然后对于每一个前缀都用一个点分树来维护,不难在$O(\log n)$的时间内处理掉一组询问。现在问题在于如何构建可持久化点分树。

首先,点分树的深度是$O(\log n)$的,所以我们在加入一个新点的时候可以新建这个点到根的那条链。而对于2操作,我们只需要重新构建第x棵点分树就好了。但是有一个问题,我们再新建一个点的时候需要复制这个点所有儿子的信息,但是一个点的儿子数量是$O(n)$级别的,怎么办?

这就需要我们对原树进行预处理,将多叉树转变为二叉树。具体方法:假如点x的儿子分别为$c_1,c_2,...c_k$,则我们新建k-2个点$t_1,t_2...t_{k-2}$,连边:$x-t_1,t_1-t_2,...,t_{k-3}-t_{k-2}$,$c_1-x,c_2-t_1,c_3-t_2,...c_{k-1}-t_{k-2},c_k-t_{k-2}$即可。总新建的点数显然不超过n。

那么我们在点分树上的每个点最多就只有3个儿子了。再记录一下从根走到每个点的路径就很容易处理了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=200010;
typedef long long ll;
int n,m,N,cnt,Cnt,msk,mn,tot,root;
ll ans;
int to[maxn<<2],nxt[maxn<<2],head[maxn<<1],val[maxn<<2],To[maxn<<1],Nxt[maxn<<1],Head[maxn],Val[maxn<<1];
int p[maxn],siz[maxn<<1],Log[maxn<<2],d[maxn],vis[maxn<<1],dep[maxn<<1],pos[maxn<<1],rt[maxn];
ll md[20][maxn<<2],des[maxn<<1];
vector<int> step[maxn<<1];
struct node
{
int ch[3],cnt,org; ll s1,s2;
}s[maxn*60];
inline void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,nxt[cnt]=head[a],head[a]=cnt++;
}
inline void Add(int a,int b,int c)
{
To[Cnt]=b,Val[Cnt]=c,Nxt[Cnt]=Head[a],Head[a]=Cnt++;
}
void dfs1(int x,int fa)
{
for(int i=Head[x],last=0,tmp=0;i!=-1;i=Nxt[i]) if(To[i]!=fa)
{
tmp++;
if(tmp==1) add(x,To[i],Val[i]),add(To[i],x,Val[i]),last=x;
else if(tmp==d[x]-(x!=1)) add(last,To[i],Val[i]),add(To[i],last,Val[i]);
else
{
N++,add(last,N,0),add(N,last,0),last=N;
add(N,To[i],Val[i]),add(To[i],N,Val[i]);
}
}
for(int i=Head[x];i!=-1;i=Nxt[i]) if(To[i]!=fa) dfs1(To[i],x);
}
void dfs2(int x,int fa)
{
md[0][++pos[0]]=des[x],pos[x]=pos[0];
for(int i=head[x];i!=-1;i=nxt[i]) if(to[i]!=fa) des[to[i]]=des[x]+val[i],dfs2(to[i],x),md[0][++pos[0]]=des[x];
}
void getrt(int x,int fa)
{
siz[x]=1;
int tmp=0,i;
for(i=head[x];i!=-1;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa)
{
getrt(to[i],x),siz[x]+=siz[to[i]],tmp=max(tmp,siz[to[i]]);
}
tmp=max(tmp,tot-siz[x]);
if(tmp<mn) mn=tmp,root=x;
}
void solve(int x)
{
vis[x]=1,s[x].org=x;
for(int i=head[x];i!=-1;i=nxt[i]) if(!vis[to[i]])
{
tot=siz[to[i]],mn=1<<30,getrt(to[i],x),dep[root]=dep[x]+1;
for(int j=0;j<dep[x];j++) step[root].push_back(step[x][j]);
if(!s[x].ch[0]) s[x].ch[0]=root,step[root].push_back(0);
else if(!s[x].ch[1]) s[x].ch[1]=root,step[root].push_back(1);
else s[x].ch[2]=root,step[root].push_back(2);
solve(root);
}
}
inline ll lca(int a,int b)
{
a=pos[a],b=pos[b];
if(a>b) swap(a,b);
int k=Log[b-a+1];
return min(md[k][a],md[k][b-(1<<k)+1]);
}
inline ll dis(int a,int b)
{
return des[a]+des[b]-2*lca(a,b);
}
void insert(int x,int &y,int a,int b,int fa)
{
y=++tot;
int z=s[x].org;
memcpy(s[y].ch,s[x].ch,sizeof(s[y].ch)),s[y].org=z;
s[y].cnt=s[x].cnt+b,s[y].s1=s[x].s1+b*dis(z,a),s[y].s2=s[x].s2;
if(fa) s[y].s2+=b*dis(s[fa].org,a);
if(s[y].org==a) return ;
insert(s[x].ch[step[a][dep[z]]],s[y].ch[step[a][dep[z]]],a,b,y);
}
ll find(int x,int y)
{
int i,u;
ll ret=0;
for(i=0;i<dep[y];i++)
{
u=s[x].ch[step[y][i]];
ret+=(s[x].cnt-s[u].cnt)*dis(s[x].org,y)+(s[x].s1-s[u].s2);
x=u;
}
return ret+s[x].s1;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
//freopen("cf757G.in","r",stdin);
N=n=rd(),m=rd(),msk=(1<<30)-1;
int i,j,a,b,c;
for(i=1;i<=n;i++) p[i]=rd();
memset(head,-1,sizeof(head)),memset(Head,-1,sizeof(Head));
for(i=1;i<n;i++) a=rd(),b=rd(),c=rd(),Add(a,b,c),Add(b,a,c),d[a]++,d[b]++;
dfs1(1,0),dfs2(1,0);
for(i=2;i<=pos[0];i++) Log[i]=Log[i>>1]+1;
for(j=1;(1<<j)<=pos[0];j++) for(i=1;i+(1<<j)-1<=pos[0];i++) md[j][i]=min(md[j-1][i],md[j-1][i+(1<<(j-1))]);
tot=N,mn=1<<30,getrt(1,0),rt[0]=root,solve(root);
tot=N;
for(i=1;i<=n;i++)
insert(rt[i-1],rt[i],p[i],1,0);
for(i=1;i<=m;i++)
{
if(rd()==1)
{
a=rd()^ans,b=rd()^ans,c=rd()^ans;
ans=find(rt[b],c)-find(rt[a-1],c);
printf("%lld\n",ans);
ans&=msk;
}
else
{
a=rd()^ans;
insert(rt[a-1],rt[a],p[a],0,0),swap(p[a],p[a+1]),insert(rt[a],rt[a],p[a],1,0);
}
}
return 0;
}//5 5 4 5 1 3 2 4 2 4 1 3 9 4 1 4 4 5 2 1 1 5 4 1 22 20 20 2 38 2 39 1 36 38 38

【CF757G】Can Bash Save the Day? 可持久化点分树的更多相关文章

  1. CF757G Can Bash Save the Day?

    CF757G Can Bash Save the Day? #include<bits/stdc++.h> #define RG register #define IL inline #d ...

  2. [Codeforces757G]Can Bash Save the Day?——动态点分治(可持久化点分树)

    题目链接: Codeforces757G 题目大意:给出一棵n个点的树及一个1~n的排列pi,边有边权,有q次操作: 1 l r x 求 $\sum\limits_{i=l}^{r}dis(p_{i} ...

  3. 51nod 1295 XOR key 可持久化01字典树

    题意 给出一个长度为\(n\)的正整数数组\(a\),再给出\(q\)个询问,每次询问给出3个数,\(L,R,X(L<=R)\).求\(a[L]\)至\(a[R]\)这\(R-L+1\)个数中, ...

  4. HDU 6191 2017ACM/ICPC广西邀请赛 J Query on A Tree 可持久化01字典树+dfs序

    题意 给一颗\(n\)个节点的带点权的树,以\(1\)为根节点,\(q\)次询问,每次询问给出2个数\(u\),\(x\),求\(u\)的子树中的点上的值与\(x\)异或的值最大为多少 分析 先dfs ...

  5. FHQ Treap及其可持久化与朝鲜树式重构

    FHQ Treap,又称无旋treap,一种不基于旋转机制的平衡树,可支持所有有旋treap.splay等能支持的操作(只有在LCT中会比splay复杂度多一个log).最重要的是,它是OI中唯一一种 ...

  6. 洛谷P3919 【模板】可持久化数组 [主席树]

    题目传送门 可持久化数组 题目描述 如题,你需要维护这样的一个长度为 $N$ 的数组,支持如下几种操作 在某个历史版本上修改某一个位置上的值 访问某个历史版本上的某一位置的值 此外,每进行一次操作(对 ...

  7. P5283 [十二省联考2019]异或粽子 可持久化01Trie+线段树

    $ \color{#0066ff}{ 题目描述 }$ 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 \(n\) 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 ...

  8. luogu 2483 K短路 (可持久化左偏树)

    题面: 题目大意:给你一张有向图,求1到n的第k短路 $K$短路模板题 假设整个图的边集为$G$ 首先建出以点$n$为根的,沿反向边跑的最短路树,设这些边构成了边集$T$ 那么每个点沿着树边走到点$n ...

  9. luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树

    LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...

随机推荐

  1. 【转帖】Linux发行版:CentOS、Ubuntu、RedHat、Android、Tizen、MeeGo

     Linux发行版:CentOS.Ubuntu.RedHat.Android.Tizen.MeeGo作者:阳光岛主 原文在这儿 Linux,最早由Linus Benedict Torvalds在199 ...

  2. 为npm设置代理

    npm全称为Node Packaged Modules.它是一个用于管理基于node.js编写的package的命令行工具.其本身就是基于node.js写的,这有点像gem与ruby的关系. 在我们的 ...

  3. ZooKeeper学习之-Zookeeper简单介绍(一)

    一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技术.那么什么是分布式协调技术?那么我来告诉大家,其实分布式协调技术主要用来解决分布式环境当中多个进程之间的同 ...

  4. mongodb 3.2.x 启动 Warning 错误处理

    [root@restore1 data1]# mongod --dbpath=/data/data1/mongodb_data/ --directoryperdb ** WARNING: You ar ...

  5. 好用的图片缩放JS

    <!DOCTYPE HTML> <meta charset="UTF-8"> <head> <script src="jquer ...

  6. 一个基于jquery的智能提示控件intellSeach.js

    一.需求 我们经常会遇到[站内搜索]的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示.例如:某公司人事管理系统,想搜索李XX,只要输入“李”,系统自然会提示一些姓李的员工,这样方便用户 ...

  7. C语言realloc,malloc,calloc的区别【转载】

    转载自:http://www.cnblogs.com/BlueTzar/articles/1136549.html 三个函数的申明分别是: void* realloc(void* ptr, unsig ...

  8. Java中Volatile详解

    当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写.这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的 ...

  9. Dubbo -- 系统学习 笔记 -- 示例 -- 直连提供者

    Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 直连提供者 在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候 ...

  10. linux nginx svn 更新前端代码

    1.进入项目前端代码目录中 root@TServer:~# cd /home/p/web/gongti/ 2.更新svn上最新的代码版本 root@TServer:/home/p/web/gongti ...