Submission #1289968

#TimeUsernameProblemLanguageResultExecution timeMemory
1289968boclobanchatGrapevine (NOI22_grapevine)C++20
100 / 100
865 ms156356 KiB
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const long long INF=1e18;
struct subtree
{
	int n;
	vector<long long> seg,lazy;
	vector< pair<int,int> > vi;
	vector<int> R;
	int getnode(int pos) { return vi[lower_bound(vi.begin(),vi.end(),(pair<int,int>){pos,0})-vi.begin()].second; }
	void build()
	{
		n=vi.size();
		sort(vi.begin(),vi.end());
		seg.resize(n*4+2,INF),lazy.resize(n*4+2);
	}
	void down(int pos)
	{
		long long val=lazy[pos];
		seg[pos*2]+=val,seg[pos*2+1]+=val;
		lazy[pos*2]+=val,lazy[pos*2+1]+=val;
		lazy[pos]=0;
	}
	void update(int l,int r,int i,long long val,int pos)
	{
		while(l<r)
		{
			int mid=(l+r)/2;
			down(pos);
			if(i<=mid) r=mid,pos*=2;
			else l=mid+1,pos=pos*2+1;
		}
		seg[pos]=val;
		while(pos) pos/=2,seg[pos]=min(seg[pos*2],seg[pos*2+1]);
	}
	void update(int l,int r,int u,int v,int val,int pos)
	{
		if(v<l||r<u) return ;
		if(u<=l&&r<=v)
		{
			seg[pos]+=val,lazy[pos]+=val;
			return ;
		}
		int mid=(l+r)/2;
		down(pos);
		update(l,mid,u,v,val,pos*2);
		update(mid+1,r,u,v,val,pos*2+1);
		seg[pos]=min(seg[pos*2],seg[pos*2+1]);
	}
	void update(int u,long long val)
	{
		u=getnode(u);
		update(1,n,u,val,1);
	}
	void update(int u,int v,int w)
	{
		u=getnode(u),v=getnode(v);
		if(u>v) swap(u,v);
		update(1,n,v,R[v],w,1);
	}
};
vector< pair<int,int> > ds[MAXN];
int sp[MAXN][20],dis[MAXN],root[MAXN],sub[MAXN],L[MAXN],R[MAXN],D[MAXN],F[MAXN],dep[MAXN],tdfs=0,cnt=0;
long long fen[MAXN];
bool ck[MAXN];
subtree T[MAXN];
void update(int i,int n,int val) { for(;i<=n;i+=i&-i) fen[i]+=val; }
long long get(int i) { long long ans=0;for(;i;i-=i&-i) ans+=fen[i];return ans; }
void dfs(int i,int pre)
{
	sp[i][0]=pre,L[i]=++tdfs;
	for(int j=1;j<=16;j++) sp[i][j]=sp[sp[i][j-1]][j-1];
	for(auto v:ds[i]) if(v.first!=pre)
	{
		dis[v.first]=dis[i]+1,F[v.first]=v.second;
		dfs(v.first,i);
	}
	R[i]=tdfs;
}
int lca(int a,int b)
{
	int x=dis[a],y=dis[b],m=min(x,y);
	for(int i=16;i+1;i--)
	{
		if((x-m)&(1<<i)) a=sp[a][i];
		if((y-m)&(1<<i)) b=sp[b][i];
	}
	if(a==b) return a;
	for(int i=16;i+1;i--) if(sp[a][i]!=sp[b][i]) a=sp[a][i],b=sp[b][i];
	return sp[a][0];
}
long long getdis(int a,int b) { return get(L[a])+get(L[b])-get(L[lca(a,b)])*2; }
void dfs2(int i,int pre)
{
	sub[i]=1;
	for(auto v:ds[i]) if(v.first!=pre&&!ck[v.first])
	{
		dfs2(v.first,i);
		sub[i]+=sub[v.first];
	}
}
void dfs3(int i,int pre,int rt)
{
	L[i]=++tdfs;
	T[rt].vi.push_back({i,tdfs});
	for(auto v:ds[i]) if(v.first!=pre&&!ck[v.first])
	{
		D[v.first]=D[i]+1;
		dfs3(v.first,i,rt);
	}
	T[rt].R[L[i]]=tdfs;
}
int centroid(int i,int pre,int c)
{
	for(auto v:ds[i]) if(v.first!=pre&&!ck[v.first]&&sub[v.first]*2>=c) return centroid(v.first,i,c);
	return i;
}
void decomp(int i,int pre)
{
	dfs2(i,i);
	int pos=centroid(i,i,sub[i]);
	ck[pos]=true,root[pos]=pre,dep[pos]=dep[pre]+1,D[pos]=tdfs=0;
	T[pos].R.resize(sub[i]+1);
	dfs3(pos,pos,pos);
	T[pos].build();
	for(auto v:ds[pos]) if(!ck[v.first]) decomp(v.first,pos);
}
void update(int pos)
{
	int p=pos;
	if(!ck[pos])
	{
		ck[pos]=true,cnt++;
		while(pos) T[pos].update(p,getdis(pos,p)),pos=root[pos];
	}
	else
	{
		ck[pos]=false,cnt--;
		while(pos) T[pos].update(p,INF),pos=root[pos];
	}
}
void update(int u,int v,int w,int n)
{
	if(dis[u]>dis[v]) swap(u,v);
	w-=F[v],F[v]+=w;
	update(L[v],n,w);
	update(R[v]+1,n,-w);
	if(dep[u]>dep[v]) swap(u,v);
	int node=u;
	while(node) T[node].update(u,v,w),node=root[node];
}
long long solve(int pos)
{
	if(!cnt) return -1;
	long long ans=INF;
	int p=pos;
	while(pos) ans=min(ans,T[pos].seg[1]+getdis(pos,p)),pos=root[pos];
	return ans;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n,q;
    cin>>n>>q;
    for(int i=1;i<n;i++)
    {
    	int l,r,v;
    	cin>>l>>r>>v;
    	ds[l].push_back({r,v}),ds[r].push_back({l,v});
	}
	decomp(1,0);
	tdfs=0;
	dfs(1,1);
	for(int i=2;i<=n;i++)
	{
		update(L[i],n,F[i]);
		update(R[i]+1,n,-F[i]);
	}
	for(int i=1;i<=n;i++) ck[i]=false;
	while(q--)
	{
		int t;
		cin>>t;
		if(t==1)
		{
			int p;
			cin>>p;
			cout<<solve(p)<<"\n";
		}
		else if(t==2)
		{
			int p;
			cin>>p;
			update(p);
		}
		else
		{
			int u,v,w;
			cin>>u>>v>>w;
			update(u,v,w,n);
		}
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...