记录编号 96165 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [POJ 3237] 树的维护 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.998 s
提交时间 2014-04-11 16:04:30 内存使用 2.69 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
const int SIZEN=10010,INF=0x7fffffff/2;
class NODE{//线段树的节点
public:
	int left,right;
	int lc,rc;
	int mx,mn;//最大值和最小值
	bool inv;//是否应当取反
	void negate(void){
		swap(mx,mn);
		mx*=-1,mn*=-1;
		inv^=1;
	}
	void assign(int x){//整段赋x
		mx=mn=x;
		inv=false;
	}
};
int treetot;
NODE tree[SIZEN*2];
int build(int x,int y){//默认值为0
	int p=treetot++;
	NODE &now=tree[p];
	now.left=x,now.right=y;
	now.assign(0);
	if(x<y){
		int mid=(x+y)/2;
		now.lc=build(x,mid);
		now.rc=build(mid+1,y);
	}
	else now.lc=now.rc=-1;
	return p;
}
void pushdown(int root){
	if(root==-1) return;
	NODE &now=tree[root];
	if(now.lc==-1) return;
	if(now.inv){
		tree[now.lc].negate();
		tree[now.rc].negate();
		now.inv=false;
	}
}
void update(int root){
	if(root==-1) return;
	NODE &now=tree[root];
	if(now.lc==-1) return;
	NODE &lson=tree[now.lc],&rson=tree[now.rc];
	now.mx=max(lson.mx,rson.mx);
	now.mn=min(lson.mn,rson.mn);
}
void singlechange(int root,int x,int t){//改一个点的权值
	if(root==-1) return;
	pushdown(root);
	NODE &now=tree[root];
	if(now.right<x||now.left>x) return;
	if(now.lc==-1) now.assign(t);//就是这个点
	else{
		singlechange(now.lc,x,t);
		singlechange(now.rc,x,t);
		update(root);
	}
}
void segnegate(int root,int x,int y){
	if(root==-1) return;
	NODE &now=tree[root];
	pushdown(root);
	if(now.right<x||now.left>y) return;
	if(now.left>=x&&now.right<=y) now.negate();//完全取反
	else{
		segnegate(now.lc,x,y);
		segnegate(now.rc,x,y);
		update(root);
	}
}
int segmax(int root,int x,int y){
	if(root==-1) return -INF;
	NODE &now=tree[root];
	pushdown(root);
	if(now.right<x||now.left>y) return -INF;
	if(now.left>=x&&now.right<=y) return now.mx;
	else return max(segmax(now.lc,x,y),segmax(now.rc,x,y));
}
class CHAIN{//一条树链
public:
	int tpos;//对应线段树根的下标
	int top;//最上面的节点
};
CHAIN tc[SIZEN];//树链的信息
int tcnum;
int cbelong[SIZEN]={0};//属于哪一条链
int ufs[SIZEN]={0};
int grand(int x){
	return !ufs[x]?x:ufs[x]=grand(ufs[x]);
}
int segpos[SIZEN]={0};//在链中
int N;
vector<pair<int,int> > c[SIZEN];
int edgew[SIZEN]={0};//边的权重
int lv[SIZEN]={0};//边对应哪个点
int father[SIZEN]={0},depth[SIZEN]={0};
int dfslis[SIZEN*2]={0},dfslen;//dfslis的大小必须是2SIZEN,否则会跪
int dfn[SIZEN]={0};
int weight[SIZEN]={0};//点的权重
int ST[SIZEN*2][20]={0};
void ST_prepare(void){
	int m=floor(log(dfslen+0.0)/log(2.0));
	for(int i=1;i<=dfslen;i++) ST[i][0]=dfslis[i];
	for(int j=1;j<=m;j++){
		for(int i=1;i<=dfslen;i++){
			if(i+(1<<j)-1>dfslen) break;
			int x=ST[i][j-1],y=ST[i+(1<<(j-1))][j-1];
			ST[i][j]=depth[x]<depth[y]?x:y;
		}
	}
}
int STLCA(int a,int b){
	if(dfn[a]>dfn[b]) swap(a,b);
	int l=dfn[a],r=dfn[b];//[l,r]区间最浅
	int m=floor(log(r-l+1.0)/log(2.0));
	int x=ST[l][m],y=ST[r-(1<<m)+1][m];
	return depth[x]<depth[y]?x:y;
}
void grandnegate(int anc,int x){//anc~x之间的全部取反
	int k=cbelong[x],tp=tc[k].top;//tp是链的最上点
	while(depth[tp]>depth[anc]){
		segnegate(tc[k].tpos,segpos[x],segpos[tp]);
		x=father[tp];
		k=cbelong[x],tp=tc[k].top;
	}
	if(x==anc) return;
	segnegate(tc[k].tpos,segpos[x],segpos[anc]-1);
}
void pathnegate(int a,int b){
	int anc=STLCA(a,b);
	grandnegate(anc,a);
	grandnegate(anc,b);
}
int grandmax(int anc,int x){//返回anc~x之间的最大值
	int ans=-INF;
	int k=cbelong[x],tp=tc[k].top;
	while(depth[tp]>depth[anc]){
		ans=max(ans,segmax(tc[k].tpos,segpos[x],segpos[tp]));
		x=father[tp];
		k=cbelong[x],tp=tc[k].top;
	}
	if(x==anc) return ans;
	ans=max(ans,segmax(tc[k].tpos,segpos[x],segpos[anc]-1));
	return ans;
}
int getmax(int a,int b){
	int anc=STLCA(a,b);
	return max(grandmax(anc,a),grandmax(anc,b));
}
void nodechange(int x,int t){
	int k=cbelong[x];
	singlechange(tc[k].tpos,segpos[x],t);
}
int DFS(int x){//返回从x开始的链的长度
	dfslis[++dfslen]=x;dfn[x]=dfslen;
	int best=0,bestlen=0;//bestlen是最长链的长度
	for(int i=0;i<c[x].size();i++){
		int u=c[x][i].first;
		if(u!=father[x]){
			weight[u]=edgew[c[x][i].second];
			lv[c[x][i].second]=u;
			depth[u]=depth[x]+1;
			father[u]=x;
			int now=DFS(u);
			if(now>bestlen){
				if(best){
					cbelong[best]=++tcnum;
					tc[tcnum].top=best;
					tc[tcnum].tpos=build(1,bestlen);
				}
				bestlen=now;
				best=u;
			}
			else{//u向下的链被截断
				cbelong[u]=++tcnum;
				tc[tcnum].top=u;
				tc[tcnum].tpos=build(1,now);
			}
			dfslis[++dfslen]=x;
		}
	}
	ufs[best]=x;//如果best是0不会产生影响
	segpos[x]=bestlen+1;
	return bestlen+1;
}
void globalclear(int N){//丧心病狂的单文件多数据!!!!
	treetot=0;
	tcnum=0;
	memset(cbelong,0,sizeof(cbelong));
	memset(ufs,0,sizeof(ufs));
	memset(segpos,0,sizeof(segpos));
	for(int i=1;i<=N;i++) c[i].clear();
	memset(edgew,0,sizeof(edgew));
	memset(lv,0,sizeof(lv));
	memset(father,0,sizeof(father));
	memset(depth,0,sizeof(depth));
	memset(dfslis,0,sizeof(dfslis));
	dfslen=0;
	memset(dfn,0,sizeof(dfn));
	memset(weight,0,sizeof(weight));
}
void work(void){
	char cmd[10]={0};
	int x,y,t;
	while(true){
		scanf("%s",cmd);
		if(!strcmp(cmd,"DONE")) break;
		if(!strcmp(cmd,"CHANGE")){
			scanf("%d%d",&x,&t);
			nodechange(lv[x],t);
		}
		else if(!strcmp(cmd,"NEGATE")){
			scanf("%d%d",&x,&y);
			pathnegate(x,y);
		}
		else if(!strcmp(cmd,"QUERY")){
			scanf("%d%d",&x,&y);
			printf("%d\n",getmax(x,y));
		}
	}
}
void init(void){
	int L=DFS(1);
	cbelong[1]=++tcnum;
	tc[tcnum].top=1;
	tc[tcnum].tpos=build(1,L);
	for(int i=1;i<=N;i++) cbelong[i]=cbelong[grand(i)];
	for(int i=1;i<=N;i++) nodechange(i,weight[i]);
	ST_prepare();
}
void read(void){
	scanf("%d",&N);
	globalclear(N);
	int a,b,w;
	for(int i=1;i<N;i++){
		scanf("%d%d%d",&a,&b,&w);
		edgew[i]=w;
		c[a].push_back(make_pair(b,i));
		c[b].push_back(make_pair(a,i));
	}
}
int main(){
	freopen("maintaintree.in","r",stdin);
	freopen("maintaintree.out","w",stdout);
	read();
	init();
	work();
	/*int T;
	scanf("%d",&T);
	while(T--){
		read();
		init();
		work();
	}*/
	return 0;
}