记录编号 142841 评测结果 AAAAAAAAAA
题目名称 [国家集训队2011]旅游 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.257 s
提交时间 2014-12-11 09:11:41 内存使用 25.88 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int SIZEN=100010,INF=0x7fffffff/2;
class Data{
public:
	int mn,mx,sum;
	void operator = (int x){mn=mx=sum=x;}
};
Data operator + (Data a,Data b){
	a.mn=min(a.mn,b.mn);
	a.mx=max(a.mx,b.mx);
	a.sum+=b.sum;
	return a;
}
const Data Zero_Data=(Data){INF,-INF,0};//一个"无影响"的Data值
class Node{//线段树的节点
public:
	int a,b;
	int lc,rc;
	bool inv;
	Data key;
	void Inverse(void){//取反
		inv^=1;
		key.sum*=-1;key.mn*=-1;key.mx*=-1;
		swap(key.mn,key.mx);
	}
};
class Segment_Tree{
public:
	Node Tree[SIZEN*2];
	int tot;
	void Clear(void){tot=0;}
	Segment_Tree(void){Clear();}
	void Update(int p){
		if(!p) return;
		Node &now=Tree[p];
		if(!now.lc) return;
		now.key=Tree[now.lc].key+Tree[now.rc].key;
	}
	void Push_Down(int p){
		if(!p) return;
		Node &now=Tree[p];
		if(!now.lc) return;
		if(now.inv){
			Tree[now.lc].Inverse();
			Tree[now.rc].Inverse();
			now.inv=0;
		}
	}
	int Build(int a[],int l,int r){//把序列a建树
		int p=++tot;
		Node &now=Tree[p];
		now.a=l,now.b=r,now.inv=0;
		if(l==r){
			now.lc=now.rc=0;
			now.key=a[l];
		}
		else{
			int mid=(l+r)/2;
			now.lc=Build(a,l,mid);
			now.rc=Build(a,mid+1,r);
			Update(p);
		}
		return p;
	}
	void Modify_Single(int p,int x,int t){//在p中把x改成t
		if(!p) return;
		Push_Down(p);
		Node &now=Tree[p];
		if(now.a>x||now.b<x) return;
		if(now.a==x&&now.b==x) now.key=t;
		else{
			Modify_Single(now.lc,x,t);
			Modify_Single(now.rc,x,t);
			Update(p);
		}
	}
	void Modify_Inverse(int p,int x,int y){//在p中把[x,y]取反
		if(!p) return;
		Push_Down(p);
		Node &now=Tree[p];
		if(now.a>y||now.b<x) return;
		if(now.a>=x&&now.b<=y) now.Inverse();
		else{
			Modify_Inverse(now.lc,x,y);
			Modify_Inverse(now.rc,x,y);
			Update(p);
		}
	}
	Data Query(int p,int l,int r){
		if(!p) return Zero_Data;
		Push_Down(p);
		Node &now=Tree[p];
		if(now.a>r||now.b<l) return Zero_Data;
		if(now.a>=l&&now.b<=r) return now.key;
		return Query(now.lc,l,r)+Query(now.rc,l,r);
	}
};
class Edge{
public:
	int to,id,w;
};
vector<Edge> G[SIZEN];
void Add_Edge(int a,int b,int id,int w){
	G[a].push_back((Edge){b,id,w});
}
int N;
Segment_Tree SGT;
int root[SIZEN]={0},top[SIZEN]={0};
int depth[SIZEN]={0},height[SIZEN]={0};
int fa[SIZEN]={0},falen[SIZEN]={0};
int belong[SIZEN]={0};
int Vid[SIZEN]={0};//对应的点(父子边对应其儿子)
int DFS_lis[SIZEN*2],DFS_len=0;
int vistim[SIZEN];
int ST[SIZEN*2][18];
int log_2(int x){
	int ans=-1;
	while(x) x>>=1,ans++;
	return ans;
}
int ST_LCA(int a,int b){
	int l=vistim[a],r=vistim[b];
	if(l>r) swap(l,r);
	int m=log_2(r-l+1);
	int x=ST[l][m],y=ST[r-(1<<m)+1][m];
	return depth[x]<depth[y]?x:y;
}
void ANC_Path_Inverse(int a,int b){//a是b的祖先
	if(depth[a]>=depth[b]) return;
	while(b){
		int k=belong[b];
		int l=max(depth[a]+1,depth[top[k]]);
		SGT.Modify_Inverse(root[k],l,depth[b]);
		if(depth[fa[top[k]]]>depth[a]) b=fa[top[k]];
		else break;
	}
}
void Path_Inverse(int a,int b){//路径翻转
	int g=ST_LCA(a,b);
	ANC_Path_Inverse(g,a);
	ANC_Path_Inverse(g,b);
}
void Edge_Modify(int x,int t){//x号路径改为t
	int u=Vid[x];
	SGT.Modify_Single(root[belong[u]],depth[u],t);
}
Data ANC_Path_Query(int a,int b){//a是b的祖先
	if(depth[a]>=depth[b]) return Zero_Data;
	Data ans=Zero_Data;
	while(b){
		int k=belong[b];
		int l=max(depth[a]+1,depth[top[k]]);
		ans=ans+SGT.Query(root[k],l,depth[b]);
		if(depth[fa[top[k]]]>depth[a]) b=fa[top[k]];
		else break;
	}
	return ans;
}
Data Path_Query(int a,int b){//路径查询
	int g=ST_LCA(a,b);
	return ANC_Path_Query(g,a)+ANC_Path_Query(g,b);
}
void Process(void){
	int Q;
	scanf("%d",&Q);
	char cmd[10]={0};
	int x,y;
	for(int i=1;i<=Q;i++){
		scanf("%s",cmd);
		scanf("%d%d",&x,&y);
		if(cmd[0]=='C') Edge_Modify(x,y);
		else if(cmd[0]=='N') Path_Inverse(x+1,y+1);
		else{
			Data D=Path_Query(x+1,y+1);
			if(cmd[0]=='S') printf("%d\n",D.sum);
			else if(cmd[1]=='A') printf("%d\n",D.mx);
			else if(cmd[1]=='I') printf("%d\n",D.mn);
		}
	}
}
void ST_LCA_Prepare(void){
	int m=log_2(DFS_len);
	for(int i=1;i<=DFS_len;i++) ST[i][0]=DFS_lis[i];
	for(int j=1;j<=m;j++){
		for(int i=1;i<=DFS_len;i++){
			if(i+(1<<j)-1>DFS_len) continue;
			int x=ST[i][j-1],y=ST[i+(1<<(j-1))][j-1];
			ST[i][j]=depth[x]<depth[y]?x:y;
		}
	}
}
void DFS(int x){
	height[x]=0;
	belong[x]=x;
	DFS_lis[++DFS_len]=x;
	vistim[x]=DFS_len;
	for(int i=0;i<G[x].size();i++){
		Edge &e=G[x][i];
		if(e.to!=fa[x]){
			fa[e.to]=x;falen[e.to]=e.w;
			depth[e.to]=depth[x]+1;
			Vid[e.id]=e.to;
			DFS(e.to);
			if(height[e.to]+1>height[x]){
				height[x]=height[e.to]+1;
				belong[x]=belong[e.to];
			}
			DFS_lis[++DFS_len]=x;
		}
	}
}
void Init_Chain(int x){//从x向上
	static int W[SIZEN];
	int y=x;
	W[depth[x]]=falen[x];
	while(fa[y]&&belong[fa[y]]==x){
		y=fa[y];
		W[depth[y]]=falen[y];
	}
	root[x]=SGT.Build(W,depth[y],depth[x]);
	top[x]=y;
}
void Prepare(void){
	depth[1]=fa[1]=DFS_len=0;
	DFS(1);
	ST_LCA_Prepare();
	for(int i=1;i<=N;i++)
		if(belong[i]==i) Init_Chain(i);
}
void Read(void){
	scanf("%d",&N);
	int u,v,w;
	for(int i=1;i<N;i++){
		scanf("%d%d%d",&u,&v,&w);
		u++,v++;
		Add_Edge(u,v,i,w);
		Add_Edge(v,u,i,w);
	}
}
int main(){
	freopen("nt2011_travel.in","r",stdin);
	freopen("nt2011_travel.out","w",stdout);
	Read();
	Prepare();
	Process();
	return 0;
}