CF757G Can Bash Save the Day?

发布时间 2023-12-19 16:34:12作者: blueparrot

牛子题

先观察询问怎么处理,因为是棵树,直接拆 \(dis\) ,有 \(dis(p_i,x)=dis[p_i]+dis[x]-2\times dis[lca]\) ,前两项很好处理,但是对于 \(dis[lca(p_i,x)],i \in [l,r]\) 比较难处理,但是可以转化成经过这条边的次数再乘上边权,求一个点到根加1,一个点到根查询,所以树剖+主席树很好搞,然后注意空间,定期重构,多个位置没必要多次开点,还要标记永久化。

#include<bits/stdc++.h>
#define il inline 
#define maxn 200003
using namespace std;
typedef long long ll;
const ll mod=1ll<<30;
il int read(){
	char c;int x=0,f=0;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))x=(x*10)+(c^48),c=getchar();
	return f?-x:x;
}
struct E{
	int Next,to,w;
}edge[maxn<<1];
int n,m,cnt,head[maxn],p[maxn],a[maxn],siz[maxn],fa[maxn],hson[maxn];
int dfn[maxn],num=0,rev[maxn],Top[maxn];
ll dis[maxn],sumd[maxn],pre[maxn];
int ls[38000005],rs[38000005],tag[38000005];
ll sum[38000005];
int tot,root[maxn];
il void addedge(int from,int to,int w){
	edge[++cnt]={head[from],to,w};
	head[from]=cnt;
}
void dfs1(int x,int FA){
	fa[x]=FA,siz[x]=1;
	for(int i=head[x];i;i=edge[i].Next){
		int to=edge[i].to,w=edge[i].w;
		if(to==FA)continue;
		a[to]=w,dis[to]=dis[x]+w;
		dfs1(to,x);
		siz[x]+=siz[to];
		if(siz[to]>siz[hson[x]])hson[x]=to;
	}
}
void dfs2(int x,int u){
	Top[x]=u,dfn[x]=++num,rev[num]=x;
	if(!hson[x])return;
	dfs2(hson[x],u);
	for(int i=head[x];i;i=edge[i].Next){
		int to=edge[i].to;
		if(to!=hson[x]&&to!=fa[x])dfs2(to,to);
	}
}
int lim;
il void pushup(int x,int lt,int rt){sum[x]=sum[ls[x]]+sum[rs[x]]+tag[x]*(pre[rt]-pre[lt-1]);}
void update(int &now,int lt,int rt,int qx,int qy){
	if(now<=lim)ls[++tot]=ls[now],rs[tot]=rs[now],tag[tot]=tag[now],sum[tot]=sum[now],now=tot;
	if(lt>=qx&&rt<=qy){
		tag[now]++,sum[now]+=pre[rt]-pre[lt-1];
		return;
	}
	int mid=(lt+rt)>>1;
	if(qx<=mid)update(ls[now],lt,mid,qx,qy);
	if(qy>mid)update(rs[now],mid+1,rt,qx,qy);
	pushup(now,lt,rt);
}
il void updateR(int now,int x){
	lim=tot;
	while(x){
		update(root[now],1,n,dfn[Top[x]],dfn[x]);
		x=fa[Top[x]];
	}
}
ll query(int now,int lt,int rt,int qx,int qy){
	if(lt>=qx&&rt<=qy)return sum[now];
	int mid=(lt+rt)>>1;
	ll res=tag[now]*(pre[min(rt,qy)]-pre[max(lt,qx)-1]);
	if(qx<=mid)res+=query(ls[now],lt,mid,qx,qy);
	if(qy>mid)res+=query(rs[now],mid+1,rt,qx,qy);
	return res;
}
il ll queryR(int p,int x){
	ll res=dis[x]*p+sumd[p];
	while(x){
		res-=query(root[p],1,n,dfn[Top[x]],dfn[x])*2;
		x=fa[Top[x]];
	}
	return res;
}
int main(){
	n=read(),m=read();		
	for(int i=1;i<=n;i++)p[i]=read();
	for(int i=1;i<n;i++){	
		int u=read(),v=read(),w=read();
		addedge(u,v,w),addedge(v,u,w);
	}
	dfs1(1,0),dfs2(1,1);
	for(int i=1;i<=n;i++)sumd[i]=sumd[i-1]+dis[p[i]],pre[i]=pre[i-1]+a[rev[i]];
	for(int i=1;i<=n;i++)root[i]=root[i-1],updateR(i,p[i]);
	int opt,a,b,c,os=0;
	ll lstans=0;
	while(m--){
		opt=read(),a=lstans^read();
		if(opt==1){
			b=lstans^read(),c=lstans^read();
			lstans=queryR(b,c)-queryR(a-1,c);
			printf("%lld\n",lstans),lstans%=mod;
		}
		else{
			sumd[a]=sumd[a]-dis[p[a]]+dis[p[a+1]],swap(p[a],p[a+1]),++os;
			if(os==150000){
				os=0,tot=0;
				for(int i=1;i<=n;i++)root[i]=root[i-1],updateR(i,p[i]);
			}else root[a]=root[a-1],updateR(a,p[a]);
		}
	}
	return 0;
}