ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

杭电2022 1

2022-08-01 15:04:16  阅读:124  来源: 互联网

标签:ch int top 杭电 2022 宝藏 include stack


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有