可以帮忙调调吗(玄关)
查看原帖
可以帮忙调调吗(玄关)
426737
Little_corn楼主2024/1/14 13:20

思路是找次大值作为答案,用 树链剖分+multiset 维护,AC on #2 #4 #6

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e5+10;
int n,m,w[N];
struct edge{
	int v,next;
}edges[N<<1];
int head[N],idx;
int fa[N],siz[N],dep[N],son[N],dfn[N],rev[N],top[N];

void add_edge(int u,int v){
	idx++;
	edges[idx].v=v;
	edges[idx].next=head[u];
	head[u]=idx;
	return;
}
struct Segment_tree{
	#define ls o<<1
	#define rs o<<1|1
	#define mid (l+r>>1)
	int tmax[N<<2],ttmax[N<<2];
	void pushup(int o){ 				// 更新信息
		tmax[o]=max(tmax[ls],tmax[rs]);
		ttmax[o]=(tmax[ls]==tmax[rs])?max(ttmax[ls],ttmax[rs]):min(tmax[ls],tmax[rs]);
		return;
	}
	void build(int o,int l,int r){ 					// 建树
		if(l==r){
			tmax[o]=w[rev[l]];
			return;
		}
		build(ls,l,mid);build(rs,mid+1,r);
		pushup(o);
		return;
	}
	void modify(int o,int l,int r,int id,int k){ 			// 更新
		if(l==r){
			tmax[o]+=k;
			return;
		}
		if(id<=mid)modify(ls,l,mid,id,k);
		else modify(rs,mid+1,r,id,k);
		pushup(o);
		return;
	}
	int querymax(int o,int l,int r,int s,int t){
		if(s<=l&&r<=t)return tmax[o];
		int ret=0;
		if(s<=mid)ret=querymax(ls,l,mid,s,t);
		if(mid<t)ret=max(ret,querymax(rs,mid+1,r,s,t));
		return ret;
	}
	int querytmax(int o,int l,int r,int s,int t){ 				// 查询次大值
		if(s<=l&&r<=t)return ttmax[o];
		bool bls=(s<=mid),brs=(mid<t);
		if(bls&&brs){
			int maxls=querymax(ls,l,mid,s,t);
			int maxrs=querymax(rs,mid+1,r,s,t);
			int tmaxls=querytmax(ls,l,mid,s,t);
			int tmaxrs=querytmax(rs,mid+1,r,s,t);
			return (maxls==maxrs)?max(tmaxls,tmaxrs):min(maxls,maxrs);
		}
		else if(bls)return querytmax(ls,l,mid,s,t);
		else if(brs)return querytmax(rs,mid+1,r,s,t);
		return 0;
	}
}tree;

void dfs1(int u,int father){ 					//求前四个
	fa[u]=father;
	siz[u]=1;
	dep[u]=dep[father]+1;
	for(int i=head[u];i;i=edges[i].next){
		int v=edges[i].v;
		if(v==father)continue;
		dfs1(v,u);
		if(siz[son[u]]<siz[v])son[u]=v;
		siz[u]+=siz[v];
	}
	return;
}
int dfncnt;
void dfs2(int u,int tp){ 					// 求后三个
	dfn[u]=++dfncnt;
	rev[dfn[u]]=u;
	top[u]=tp;
	if(!son[u])return;
	dfs2(son[u],tp);
	for(int i=head[u];i;i=edges[i].next){
		int v=edges[i].v;
		if(v==fa[u]||v==son[u])continue;
		dfs2(v,v);
	}
	return;
}

multiset<int>st;

struct node{
	int tmax,ttmax;
	node(){tmax=ttmax=0;}
};

node Qnode(int x,int y){
	node ret;
	int fx=top[x],fy=top[y];
	while(fx!=fy){
		if(dep[fx]<dep[fy])swap(fx,fy),swap(x,y);
		int nowmax=tree.querymax(1,1,n,dfn[fx],dfn[x]),nowtmax=tree.querytmax(1,1,n,dfn[fx],dfn[x]);
		if(nowmax>ret.tmax){
			ret.ttmax=max(nowtmax,ret.tmax);
			ret.tmax=nowmax;
		}
		else if(nowmax!=ret.tmax)ret.ttmax=max(ret.ttmax,nowmax);
		else ret.ttmax=max(ret.ttmax,nowtmax);
		x=fa[fx];fx=top[x];
	}
	if(dfn[x]>dfn[y])swap(x,y);
	int nowmax=tree.querymax(1,1,n,dfn[x],dfn[y]),nowtmax=tree.querytmax(1,1,n,dfn[x],dfn[y]);
	if(nowmax>ret.tmax){
		ret.ttmax=max(nowtmax,ret.tmax);
		ret.tmax=nowmax;
	}
	else if(nowmax!=ret.tmax)ret.ttmax=max(ret.ttmax,nowmax);
	else ret.ttmax=max(ret.ttmax,nowtmax);
	return ret;
}

signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		add_edge(x,y);
		add_edge(y,x);
	}
	for(int i=1;i<=n;i++)cin>>w[i],st.insert(w[i]);
	dfs1(1,0);
	dfs2(1,1);
	tree.build(1,1,n);
	int T;cin>>T;
	while(T--){
		int opt,x,y;
		cin>>opt>>x>>y;
		if(opt==0){
			st.erase(st.find(w[x]));
			st.insert(w[x]+y);
			w[x]+=y;
			tree.modify(1,1,n,dfn[x],y);
		}
		if(opt==1){
			node tmp=Qnode(x,y);
			if(tmp.ttmax==0){
				cout<<-1<<"\n";
				continue;
			}
			st.erase(st.find(tmp.tmax));st.erase(st.find(tmp.ttmax));
			cout<<tmp.ttmax<<" "<<*(--st.lower_bound(*--st.end()))<<"\n";
			st.insert(tmp.tmax);st.insert(tmp.ttmax);
		}
	}
	
	return 0;
}
2024/1/14 13:20
加载中...