【CF757G】Can Bash Save the Day? 可持久化点分树
【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? 可持久化点分树的更多相关文章
- CF757G Can Bash Save the Day?
CF757G Can Bash Save the Day? #include<bits/stdc++.h> #define RG register #define IL inline #d ...
- [Codeforces757G]Can Bash Save the Day?——动态点分治(可持久化点分树)
题目链接: Codeforces757G 题目大意:给出一棵n个点的树及一个1~n的排列pi,边有边权,有q次操作: 1 l r x 求 $\sum\limits_{i=l}^{r}dis(p_{i} ...
- 51nod 1295 XOR key 可持久化01字典树
题意 给出一个长度为\(n\)的正整数数组\(a\),再给出\(q\)个询问,每次询问给出3个数,\(L,R,X(L<=R)\).求\(a[L]\)至\(a[R]\)这\(R-L+1\)个数中, ...
- HDU 6191 2017ACM/ICPC广西邀请赛 J Query on A Tree 可持久化01字典树+dfs序
题意 给一颗\(n\)个节点的带点权的树,以\(1\)为根节点,\(q\)次询问,每次询问给出2个数\(u\),\(x\),求\(u\)的子树中的点上的值与\(x\)异或的值最大为多少 分析 先dfs ...
- FHQ Treap及其可持久化与朝鲜树式重构
FHQ Treap,又称无旋treap,一种不基于旋转机制的平衡树,可支持所有有旋treap.splay等能支持的操作(只有在LCT中会比splay复杂度多一个log).最重要的是,它是OI中唯一一种 ...
- 洛谷P3919 【模板】可持久化数组 [主席树]
题目传送门 可持久化数组 题目描述 如题,你需要维护这样的一个长度为 $N$ 的数组,支持如下几种操作 在某个历史版本上修改某一个位置上的值 访问某个历史版本上的某一位置的值 此外,每进行一次操作(对 ...
- P5283 [十二省联考2019]异或粽子 可持久化01Trie+线段树
$ \color{#0066ff}{ 题目描述 }$ 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 \(n\) 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 ...
- luogu 2483 K短路 (可持久化左偏树)
题面: 题目大意:给你一张有向图,求1到n的第k短路 $K$短路模板题 假设整个图的边集为$G$ 首先建出以点$n$为根的,沿反向边跑的最短路树,设这些边构成了边集$T$ 那么每个点沿着树边走到点$n ...
- luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...
随机推荐
- [mobile angular ui]MAUI中的font awesome图标
MAUI中用font awesome替换了glyphicon,但是FA中都有哪些可用的图标呢,在网上搜了一张font awesome的对照表,使用时记着把其中的icon-xxx替换为fa-xxx就可以 ...
- ffmpeg把ts文件转m3u8并切片
Linux_x86_64流媒体环境:nginx + EasyDarwin-master 客户端播放器:VLC media player 下载windows下的ffmepg二进制版本,请进网站http: ...
- 17 HTTP编程入门
http请求原理 http请求原理我就不多说了,网上一搜就能搜索到,下面我注意是记录下http模块的使用方法 http 模块 HTTP-server hello world 我们使用HandleFun ...
- sql server 2014 序列號
亲测可用 27HMJ-GH7P9-X2TTB-WPHQC-RG79R
- 使用Eclipse构建Maven项目
http://blog.csdn.net/qjyong/article/details/9098213
- mysql中date_add()函数的使用?
需求描述: 在使用mysql的过程中,需要对日期进行计算,比如对某个日期加上几天,几个小时等操作, 在此记录下,date_add()函数的使用. 操作过程: date_add()函数语法: DATE_ ...
- UML类图关系(转,添加了实例)
UML类图关系(泛化 .继承.实现.依赖.关联.聚合.组合) 在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Associati ...
- Android应用程序的结构
1.src目录 存放该项目的源代码 2.gen目录 该目录文件是ADT自动生成的,并不需要认为地去修改 3.Android2.1 该目录存放的是该项目支持的JAR包,同时还包含项目打包时需要的META ...
- drawCall_01
在屏幕上渲染物体,引擎需要发出一个绘制调用来访问图形API(iOS系统中为OpenGL ES).每个绘制调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销. Unity在运 ...
- [Windows] 解决 COM Surrogate 错误提示
运行环境:Windows 8.1 (64bits) 异常描述:打开 "Windows 照片查看器",试图放大或缩小窗体,弹出 "COM Surrogate” 错误. 解决 ...