萌新刚学树剖2ms,只过一个点,求调
查看原帖
萌新刚学树剖2ms,只过一个点,求调
169861
模拟王子楼主2021/8/29 18:36
#include<cstdio>
#include<iostream>
#define int long long
const int maxn=2e5+1;
using namespace std;
struct node{
	int to,next,w,from;
}edge[maxn*2];
struct node1{
	int l,r,num,sum,maxn,minn,flag2;
}t[maxn*2];
char s[1001];
int u[maxn],v[maxn],w[maxn],va[maxn];
int cntt,fa1[maxn],tot,head[maxn],cnt1,ans,m,n,R,res,wt[maxn];
int mod,id[maxn],size[maxn],depth[maxn],heavyson[maxn],top[maxn];
void addedge(int u,int v,int w)
{
	edge[++cnt1].to=v;
	edge[cnt1].from=u;
	edge[cnt1].next=head[u];
	edge[cnt1].w=w;
	head[u]=cnt1;
}
void maketree(int tot,int l,int r)
{
	t[tot].l=l;
	t[tot].r=r;
	if(l==r)
	{
		t[tot].sum=wt[l];
		t[tot].maxn=wt[l];
		t[tot].minn=wt[l];
		return ;
	}
	int mid=(l+r)>>1;
	maketree(tot*2,l,mid);
	maketree(tot*2+1,mid+1,r);
	t[tot].sum=(t[tot*2].sum+t[tot*2+1].sum);
	t[tot].maxn=max(t[tot*2].maxn,t[tot*2+1].maxn);
	t[tot].minn=min(t[tot*2].minn,t[tot*2+1].minn);
}
void down(int tot,int l,int r)  // 标记下移 
{  	
	t[tot*2].flag2^=t[tot].flag2;  
	t[tot*2+1].flag2^=t[tot].flag2;  
	int mid=(l+r)/2;
	t[tot*2].sum=-t[tot*2].sum; int q=t[tot*2].minn;t[tot*2].minn=-t[tot*2].maxn,t[tot*2].maxn=-q;
	t[tot*2+1].sum=-t[tot*2+1].sum;  q=t[tot*2+1].minn;t[tot*2+1].minn=-t[tot*2+1].maxn,t[tot*2+1].maxn=-q;
	t[tot].flag2=0; 
}
void ask1(int tot,int l1,int r1,int l,int r)
{
	if(l1>=l && r1<=r)
	{
		ans+=t[tot].sum;
		return ;
	}
	if(t[tot].flag2) down(tot,l1,r1);
	int mid=(l1+r1)/2;
	if(l<=mid) ask1(tot*2,l1,mid,l,r);
	if(r>mid)  ask1(tot*2+1,mid+1,r1,l,r);
	t[tot].sum=(t[tot*2].sum+t[tot*2+1].sum);
	t[tot].maxn=max(t[tot*2].maxn,t[tot*2+1].maxn);
	t[tot].minn=min(t[tot*2].minn,t[tot*2+1].minn);
}
void ask2(int tot,int l1,int r1,int l,int r)
{
	if(l1>=l && r1<=r)
	{
		ans=max(ans,t[tot].maxn);
		return ;
	}
	if(t[tot].flag2) down(tot,l1,r1);
	int mid=(l1+r1)/2;
	if(l<=mid) ask2(tot*2,l1,mid,l,r);
	if(r>mid)  ask2(tot*2+1,mid+1,r1,l,r);
	t[tot].sum=(t[tot*2].sum+t[tot*2+1].sum);
	t[tot].maxn=max(t[tot*2].maxn,t[tot*2+1].maxn);
	t[tot].minn=min(t[tot*2].minn,t[tot*2+1].minn);
}
void ask3(int tot,int l1,int r1,int l,int r)
{
	if(l1>=l && r1<=r)
	{
		ans=min(ans,t[tot].minn);
		return ;
	}
	if(t[tot].flag2) down(tot,l1,r1);
	int mid=(l1+r1)/2;
	if(l<=mid) ask3(tot*2,l1,mid,l,r);
	if(r>mid)  ask3(tot*2+1,mid+1,r1,l,r);
	t[tot].sum=(t[tot*2].sum+t[tot*2+1].sum);
	t[tot].maxn=max(t[tot*2].maxn,t[tot*2+1].maxn);
	t[tot].minn=min(t[tot*2].minn,t[tot*2+1].minn);
}
void change1(int tot,int l,int r,int x,int y,int z)   //单点 
{
	if(l>=x && r<=y)  
	{  
		t[tot].sum=z;  
		t[tot].maxn=t[tot].sum;
		t[tot].minn=t[tot].sum;
		return ;
	}  
	if(t[tot].flag2)	down(tot,l,r);
	int mid=(l+r)/2;  
	if(x<=mid) //在左区间  
		change1(tot*2,l,mid,x,y,z);  
	if(y>mid) // 在右区间 
		change1(tot*2+1,mid+1,r,x,y,z);  
	t[tot].sum=(t[tot*2].sum+t[tot*2+1].sum);  
	t[tot].maxn=max(t[tot*2].maxn,t[tot*2+1].maxn);
	t[tot].minn=max(t[tot*2].minn,t[tot*2+1].minn);
}
void change2(int tot,int l,int r,int x,int y)   // 区间取反 
{
	if(l>=x && r<=y)  
	{  
		int q=t[tot].minn;
		t[tot].sum=-t[tot].sum;  
		t[tot].minn=-t[tot].maxn;
		t[tot].maxn=-q;
		t[tot].flag2^=1;
		return ;
	}
	if(t[tot].flag2)	down(tot,l,r);
	int mid=(l+r)/2;  
	if(x<=mid) //在左区间  
		change2(tot*2,l,mid,x,y);  
	if(y>mid) // 在右区间 
		change2(tot*2+1,mid+1,r,x,y);  
	t[tot].sum=(t[tot*2].sum+t[tot*2+1].sum);  
	t[tot].maxn=max(t[tot*2].maxn,t[tot*2+1].maxn);
	t[tot].minn=max(t[tot*2].minn,t[tot*2+1].minn);
}
///////////////////////// 以上为线段树部分 
void dfs1(int u,int fa)  // 找重儿子 
{
	fa1[u]=fa; // 父亲节点 
	depth[u]=depth[fa]+1;
	int heavy=0;
	size[u]=1;
	for(int i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(v!=fa)
		{
			int w=edge[i].w;
			va[v]=w;
			dfs1(v,u);
			size[u]+=size[v];
			if(size[v]>heavy)
			{
				heavyson[u]=v;
				heavy=size[v];
			}
		}
	}
}
void dfs2(int u,int k)
{ 
    top[u]=k; 	// 找到链头顶端 
	id[u]=++cntt; // 每个节点新编号 
	wt[cntt]=va[u];
	if(heavyson[u]) dfs2(heavyson[u],k); // 优先遍历重儿子 
	for(int i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(v==fa1[u] || v==heavyson[u]) continue;
		dfs2(v,v);
	}
}
void get2(int x,int y) // 区间和 
{
	ans=0;
	while(top[x]!=top[y])
	{
		if(depth[top[x]]<depth[top[y]])  swap(x,y); 
		ask1(1,1,n,id[top[x]],id[x]); 
		x=fa1[top[x]];
	}
	if(depth[x]>depth[y]) swap(x,y);
	ask1(1,1,n,id[x]+1,id[y]); 
	printf("%lld\n",ans);
}
void get3(int x,int y)  //最大值 
{
	ans=-0x7fffffff;
	while(top[x]!=top[y])
	{
		if(depth[top[x]]<depth[top[y]])  swap(x,y); 
		ask2(1,1,n,id[top[x]],id[x]); 
		x=fa1[top[x]];
	}
	if(depth[x]>depth[y]) swap(x,y);
	ask2(1,1,n,id[x]+1,id[y]);  
	printf("%lld\n",ans);
}
void get4(int x,int y) // 最小值 
{
	ans=0x7fffffff;
	while(top[x]!=top[y]) 
	{
		if(depth[top[x]]<depth[top[y]])  swap(x,y); 
		ask3(1,1,n,id[top[x]],id[x]); 
		x=fa1[top[x]];
	}
	if(depth[x]>depth[y]) swap(x,y);
	ask3(1,1,n,id[x]+1,id[y]);
	printf("%lld\n",ans);
}
void get5(int x,int y) // 区间 
{
	while(top[x]!=top[y])
	{
		if(depth[top[x]]<depth[top[y]])  swap(x,y); 
		change2(1,1,n,id[top[x]],id[x]); 
		x=fa1[top[x]];
	}
	if(depth[x]>depth[y]) swap(x,y);
	change2(1,1,n,id[x]+1,id[y]); 
}
signed main()
{
	scanf("%lld",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%lld%lld%lld",&u[i],&v[i],&w[i]);
		addedge(u[i]+1,v[i]+1,w[i]);addedge(v[i]+1,u[i]+1,w[i]);
	}
	dfs1(1,0);
	dfs2(1,1);
	maketree(1,1,n);
	scanf("%lld",&m);
	for(int i=1;i<=m;i++)
	{
		int k,x,y,z;
		cin>>s;	
		scanf("%lld%lld",&x,&y);
		if(s[0]=='C') 
		{
			int U=u[x]+1,V=v[x]+1;
			if(fa1[U]==V) swap(V, U);
			change1(1,1,n,id[V],id[V],y);
		}
		if(s[0]=='S'){get2(x+1,y+1);}
		if(s[0]=='M' && s[1]=='A') {get3(x+1,y+1);}
		if(s[0]=='M' && s[1]=='I') {get4(x+1,y+1);}
		if(s[0]=='N') {get5(x+1,y+1);}
	}
	return 0;
}
2021/8/29 18:36
加载中...