poj 3237 tree

Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 7409   Accepted: 2009

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers ab and c, describing an edge connecting nodes a and bwith weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

Source

POJ Monthly--2007.06.03, Lei, Tao

题目大意: 有T组数据,读入节点数N,和n-1 条边的信息,接着给出多次操作,操作以DONE结束。
QUERY  X,Y 表示求x到y 路径上的最大边权
CHANGE  X Y 表示把第X条路径的值改为Y
NEGATE  X Y 表示把X 到Y 路径上的值全部取相反数


题解: 把边权下放为点权
用线段树记录区间最小值和最大值,每次取反时,只需令max=-min, min=-max即可
处理时要格外注意细节!!  
因为边权下放为点权,所以求X,Y的路径是不能计算X点
#include
#include
#include
#include
#include
#define N 10003
#define M 20003
using namespace std;
int n,m,point[N],next[M],v[M],c[M],deep[N],size[N],pos[N],val[N],tv[N];
int tr[40003],tr1[40003],delta[40003],tot,sz,t,fa[N][15],mi[15],son[N],belong[N],ed[M],e[M];
int xx,yy; bool p;
const int inf=1e9;
void clear()
{
  tot=0; sz=0;
  memset(delta,0,sizeof(delta)); memset(point,0,sizeof(point));
  memset(next,0,sizeof(next)); memset(tr,0,sizeof(tr)); memset(tr1,0,sizeof(tr1));
  memset(fa,0,sizeof(fa)); memset(son,0,sizeof(son)); memset(e,0,sizeof(e));
  memset(ed,0,sizeof(ed)); memset(deep,0,sizeof(deep));
}
void ne(int &x,int &y)
{
  int t=x;
  x=(-1)*y;
  y=(-1)*t;
}
void add(int x,int y,int z,int num)
{
  tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z; e[tot]=num;
  tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z; e[tot]=num;
}
void dfs1(int x,int f,int dep)
{
  size[x]=1; deep[x]=dep;
  for (int i=1;i<=13;i++)
   {
   	if (deep[x]-mi[i]<0) break;
   	fa[x][i]=fa[fa[x][i-1]][i-1];
   }
  int k=0;
  for (int i=point[x];i!=0;i=next[i])
   if (v[i]!=f)
    {
      fa[v[i]][0]=x;
      val[v[i]]=c[i];  ed[e[i]]=v[i];//第I条边下放到了哪一个点 
      dfs1(v[i],x,dep+1);
      if(size[v[i]]>size[k])
       k=v[i];
      son[x]=k;
      size[x]+=size[v[i]];
    }
}
void dfs2(int x,int chain)
{
  pos[x]=++sz; tv[sz]=val[x]; belong[x]=chain;
  if (son[x])  dfs2(son[x],chain);
  for (int i=point[x];i!=0;i=next[i])
   if (deep[v[i]]>deep[x]&&v[i]!=son[x])
    dfs2(v[i],v[i]);
}
int lca(int x,int y)
{
  if (deep[x]>i&1)  x=fa[x][i];
  if (x==y) 
   return x;
  for (int i=13;i>=0;i--)
   if(fa[x][i]!=fa[y][i])
    x=fa[x][i],y=fa[y][i];
  return fa[x][0];
} 
void pushdown(int now,int l,int r)
{
  if (!delta[now]) return;
  ne(tr[now<<1],tr1[now<<1]);
  delta[now<<1]^=1;
  ne(tr[now<<1|1],tr1[now<<1|1]);
  delta[now<<1|1]^=1;
  delta[now]=0;
}
void update(int x)
{
	tr[x]=max(tr[x<<1],tr[x<<1|1]);
	tr1[x]=min(tr1[x<<1],tr1[x<<1|1]);
}
void build(int now,int l,int r)
{
  if (l==r)
   {
   	tr[now]=tr1[now]=tv[l];
   	return;
   }
  int mid=(l+r)/2;
  build(now<<1,l,mid);
  build(now<<1|1,mid+1,r);
  update(now);
}
void change(int now,int l,int r,int x,int v)
{
  if (l==r)
   {
   	tr[now]=tr1[now]=v;
   	return;
   }
  pushdown(now,l,r);
  int mid=(l+r)/2;
  if (x<=mid)
   change(now<<1,l,mid,x,v);
  else
   change(now<<1|1,mid+1,r,x,v);
  update(now);
}
int qjmax(int now,int l,int r,int ll,int rr)
{ 
  int ans=-inf;
  if (ll<=l&&r<=rr)
   {
   	  return tr[now];
   }
  pushdown(now,l,r);
  int mid=(l+r)/2;
  if (ll<=mid)
   ans=max(ans,qjmax(now<<1,l,mid,ll,rr));
  if (rr>mid)
   ans=max(ans,qjmax(now<<1|1,mid+1,r,ll,rr));
  return ans;
}
void qjch(int now,int l,int r,int ll,int rr)
{
	if (ll<=l&&r<=rr)
	 {
	 	delta[now]^=1;
	    ne(tr[now],tr1[now]);
	    return;
	 }
	pushdown(now,l,r);
	int mid=(l+r)/2;
	if (ll<=mid)  qjch(now<<1,l,mid,ll,rr);
	if (rr>mid) qjch(now<<1|1,mid+1,r,ll,rr);
	update(now);
}
int solve(int x,int f)
{
  int maxn=-inf;
  while (belong[x]!=belong[f])
   {
   	 maxn=max(maxn,qjmax(1,1,m,pos[belong[x]],pos[x]));
   	 x=fa[belong[x]][0];
   }
  if (pos[f]+1<=pos[x])
   maxn=max(maxn,qjmax(1,1,m,pos[f]+1,pos[x]));
  return maxn;
}
void solve1(int x,int f)
{
  while (belong[x]!=belong[f])
   {
   	 qjch(1,1,m,pos[belong[x]],pos[x]);
   	 x=fa[belong[x]][0];
   }
  if (pos[f]+1<=pos[x])
    qjch(1,1,m,pos[f]+1,pos[x]);
}
int main()
{
  scanf("%d",&t);
  mi[0]=1;
  for (int i=1;i<=13;i++)  mi[i]=mi[i-1]*2;
  for (int i=1;i<=t;i++)
   {
   	clear();
   	scanf("%d",&m);
   	for (int j=1;j<=m-1;j++)
   	 {
   	    int x,y,z; scanf("%d%d%d",&x,&y,&z);
   	    add(x,y,z,j);
   	 }
   	val[1]=-inf;
   	dfs1(1,0,1); dfs2(1,1);
   	char s[10]; 
   	build(1,1,m);
   	while (scanf("%s",s))
   	 {
   	 	p=false;
   	 	if (s[0]=='D') break;
   	 	if (s[0]=='N')
   	 	 {
   	 	   int x,y;  scanf("%d%d",&x,&y);
   	 	   int t=lca(x,y);
   	 	   solve1(x,t),solve1(y,t);
   	 	 }
   	 	if (s[0]=='C')
   	 	 {
   	 	 	int x,y; scanf("%d%d",&x,&y);
   	 	 	val[ed[x]]=y;
   	 	 	change(1,1,m,pos[ed[x]],y);
   	 	 }
   	 	if (s[0]=='Q')
   	 	 {
   	 	 	int x,y; scanf("%d%d",&x,&y);
   	 	 	int t=lca(x,y);
   	 	 	printf("%d\n",max(solve(x,t),solve(y,t)));
   	 	 }
   	 }
   }
}


你可能感兴趣的:(树链剖分)