其他分享
首页 > 其他分享> > 杭电2022 1

杭电2022 1

作者:互联网

1007 Treasure

\(n\)个点\(m\)条边的连通图,每个点有第\(c_i\)种权值为\(val_i\)的宝藏,问从\(x\)点出发只通过边权小于等于\(y\)的边可以获得的宝藏最大权值,每种宝藏权值只能算一遍。宝藏权值带修改。每种宝藏最多有10个。

建出克鲁斯卡尔重构树,考虑在节点上维护答案。发现每种宝藏最多有10个,所以可以建出每一种宝藏的虚树,在虚树上暴力修改。需要链上修改单点查询,树上差分之后成为单点修改,查询子树和。故使用树状数组维护克鲁斯卡尔重构树的\(dfs\)序即可。

(因为克鲁斯克鲁斯卡尔重构树的结构特殊,虚树代码有锅但是过了)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define int long long 
const int N=201000;
vector<int> vec[N];
int read(){
	int sum=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
	return sum;
}
struct Edge{
	int u,v,w;
}ed[N];
struct edge{
	int to,nxt;
}e[N*2];
int tr[N*2],dfn[N*2];
int a[N],c[N],val[N],stack[N],top,tot,n,m,root,W[N*2],Size[N*2],deep[N*2],f[N*2][21];
int cnt,head[N*2],id[N*20],mx[N*20],Map[N*20],fa[N*20];
int find(int x){
	if(fa[x]==x)return x;
	else return fa[x]=find(fa[x]);
}
void add_edge(int u,int v){
	cnt++;
	e[cnt].nxt=head[u];
	e[cnt].to=v;
	head[u]=cnt;
} 
void get_dfn(int u){
	dfn[u]=++tot;
	Size[u]=1;
	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		deep[v]=deep[u]+1;
		get_dfn(v);
		Size[u]+=Size[v];
	}
}
bool cmp_1(Edge a,Edge b){
	return a.w<b.w;
}
bool cmp_2(int a,int b){
	return dfn[a]<dfn[b]; 
}
int lowbit(int x){
	return x&-x;
}
void add(int x,int w){
	for(int i=x;i<=Size[root];i+=lowbit(i))tr[i]+=w;
}
int get_sum(int x){
	int ans=0;
	for(int i=x;i;i-=lowbit(i))ans+=tr[i];
	return ans;
}
void change(int x,int w,int last){
	mx[x]=w;
	int now=x;
	while(now){
		if(id[now]==root){
			add(dfn[id[now]],w-last);
			break;
		}
		add(dfn[id[now]],w-last);
		add(dfn[id[fa[now]]],last-w);
		if(mx[fa[now]]<w)last=mx[fa[now]],mx[fa[now]]=w,now=fa[now];
		else break;
	}
}
int jup(int x,int w){
	for(int i=20;i>=0;i--){
		if(f[x][i]==0||W[f[x][i]]>w)continue;
		x=f[x][i];
	}
	return x;
}
int get_lca(int x,int y){ 
	if(deep[x]<deep[y])swap(x,y);
	for(int i=20;i>=0;i--){
		if(deep[f[x][i]]>=deep[y])x=f[x][i];
	}
	if(x==y)return x;
	for(int i=20;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i],y=f[y][i];
		}
	} 
	return f[x][0];
}
void build_tree(){
	sort(ed+1,ed+1+m,cmp_1);
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int x=find(ed[i].u),y=find(ed[i].v);
		if(x==y)continue;
		tot++;
		fa[x]=fa[y]=fa[tot]=tot;
		f[x][0]=f[y][0]=tot;
		add_edge(tot,x);add_edge(tot,y);
		W[tot]=ed[i].w;
	}
	root=tot;
	tot=0;
	deep[root]=1;
	get_dfn(root);
	cnt=0;
	for(int i=1;i<=tot;i++)head[i]=0;
	tot=0;
} 
void rebuild_tree(){
	for(int i=1;i<=n;i++){
		if(vec[i].size()){
			a[0]=0;
			for(int j=0;j<vec[i].size();j++){
				a[++a[0]]=vec[i][j];
				sort(a+1,a+1+a[0],cmp_2);
			}
			stack[top=1]=root;
			id[++tot]=root;Map[root]=tot;
			for(int j=1;j<=a[0];j++){
				int p=a[j];
				int lca=get_lca(stack[top],p);
				if(lca==stack[top])stack[++top]=p,id[++tot]=p;
				else{
					while(top>1&&dfn[stack[top-1]]>dfn[lca]){fa[Map[stack[top]]]=Map[stack[top-1]],top--;} 
					if(dfn[stack[top-1]]<dfn[lca]){id[++tot]=lca;Map[lca]=tot;fa[Map[stack[top]]]=Map[lca];stack[top]=lca;}
					stack[++top]=p;id[++tot]=p;
				}
				Map[p]=tot;
			}
			while(top>1)fa[Map[stack[top]]]=Map[stack[top-1]],top--;
			for(int j=1;j<=a[0];j++)change(Map[a[j]],val[a[j]],0);
		}
	}
}
void clear(){
	for(int i=1;i<=n;i++)vec[i].clear();
	for(int i=1;i<=tot;i++)mx[i]=0;
	for(int i=1;i<=Size[root];i++)tr[i]=0,W[i]=0;
	for(int i=1;i<=Size[root];i++)
		for(int j=0;j<=20;j++)f[i][j]=0;
}
signed main(){
	int T=read();
	while(T--){
		n=read(),m=read();
		int q=read();
		for(int i=1;i<=n;i++)c[i]=read(),vec[c[i]].push_back(i);
		for(int i=1;i<=n;i++)val[i]=read();
		tot=n;
		for(int i=1;i<=m;i++)
			ed[i].u=read(),ed[i].v=read(),ed[i].w=read(); 
		build_tree();
		rebuild_tree();
		while(q--){
			int type=read(),x=read(),y=read();
			if(type==0){
				change(Map[x],val[x]+y,val[x]);
				val[x]+=y;
			}
			if(type==1){
				int Top=jup(x,y);
				printf("%lld\n",get_sum(dfn[Top]+Size[Top]-1)-get_sum(dfn[Top]-1));
			}
		}
		clear();
	}
	return 0;
}

标签:ch,int,top,杭电,2022,宝藏,include,stack
来源: https://www.cnblogs.com/Xu-daxia/p/16540274.html