zhber
有好多做过的题没写下来,如果我还能记得就补吧

Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

 

第三天终于调出来了

第一次写树链剖分自己cena各种wa……感觉自己快死了

感觉轻重边的剖分只是原来算法的一个贪心优化,不过要保证复杂度也是必须要用的

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define inf 598460606
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct segtree{
	int l,r,mx;
	int tot;
}tree[1000010];
struct edge{
	int to,next;
}e[200010];
int head[100010],depth[100010],son[100010],fa[100010][16];
int v[100010],place[100010],belong[100010],pplace[100010];
bool mrk[100010];
int n,m,cnt,tt,lca,treesize;
char ch[100];
inline void ins(int u,int v)
{
	e[++cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
inline void insert(int u,int v)
{
	ins(u,v);
	ins(v,u);
}
inline void dfs1(int x,int dep)
{
	if (mrk[x])return;
	mrk[x]=1;depth[x]=dep;son[x]=1;
	for(int i=1;i<=15;i++)
	  fa[x][i]=fa[fa[x][i-1]][i-1];
	for (int i=head[x];i;i=e[i].next)
	if (!mrk[e[i].to])
	{
		fa[e[i].to][0]=x;
		dfs1(e[i].to,dep+1);
		son[x]+=son[e[i].to];
	}
}
inline void dfs2(int x,int chain)
{
	int k=0,mx=0;
	place[x]=++tt;belong[x]=chain;
	pplace[tt]=x;
	for (int i=head[x];i;i=e[i].next)
	  if (fa[x][0]!=e[i].to)
	  {
	  	if (son[e[i].to]>mx)
	  	{
	  		mx=son[e[i].to];
	  		k=e[i].to;
	  	}
	  }
	if(!k)return;
	dfs2(k,chain);
	for(int i=head[x];i;i=e[i].next)
	  if (e[i].to!=k&&e[i].to!=fa[x][0])
	  	dfs2(e[i].to,e[i].to);
}
inline void update(int k)
{
	tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
	tree[k].tot=tree[k<<1].tot+tree[k<<1|1].tot;
}
inline void buildtree(int now,int l,int r)
{
	tree[now].l=l;tree[now].r=r;
	if (l==r)
	{
		tree[now].mx=v[pplace[l]];
		tree[now].tot=v[pplace[l]];
		return;
	}
	int mid=(l+r)>>1;
	buildtree(now<<1,l,mid);
	buildtree(now<<1|1,mid+1,r);
	update(now);
}
inline int LCA(int a,int b)
{
	if (depth[a]<depth[b])swap(a,b);
	int res=depth[a]-depth[b];
	for (int i=0;i<=15;i++)
	  if (res & (1<<i))a=fa[a][i];
	for (int i=15;i>=0;i--)
	  if (fa[a][i]!=fa[b][i])
	  {
	  	a=fa[a][i];
	  	b=fa[b][i];
	  }
	if(a==b)return a;
	return fa[a][0];
}
inline int ask_in_tree(int now,int x,int y)
{
	int l=tree[now].l,r=tree[now].r;
	if (l==x&&y==r)return tree[now].mx;
	int mid=(l+r)>>1;
	if (y<=mid)return ask_in_tree(now<<1,x,y);
	else if (x>mid)return ask_in_tree(now<<1|1,x,y);
	return max(ask_in_tree(now<<1,x,mid),ask_in_tree(now<<1|1,mid+1,y));
}
inline int sum_in_tree(int now,int x,int y)
{
	int l=tree[now].l,r=tree[now].r;
	if (l==x&&y==r)return tree[now].tot;
	int mid=(l+r)>>1;
	if (y<=mid)return sum_in_tree(now<<1,x,y);
	else if (x>mid)return sum_in_tree(now<<1|1,x,y);
	return sum_in_tree(now<<1,x,mid)+sum_in_tree(now<<1|1,mid+1,y);
}
inline int ask(int from,int to)
{
	int l,r,mx=-inf;
	while (belong[from]!=belong[to])
	{
		l=place[belong[from]];
		r=place[from];
		mx=max(mx,ask_in_tree(1,l,r));
		from=fa[belong[from]][0];
		
	}
	l=place[to];
	r=place[from];
	mx=max(mx,ask_in_tree(1,l,r));
	
	return mx;
}
inline int sum(int from,int to)
{
	int l,r;
	int s=0;
	while (belong[from]!=belong[to])
	{
		l=place[belong[from]];
		r=place[from];
		s+=sum_in_tree(1,l,r);
		from=fa[belong[from]][0];
	}
	l=place[to];
	r=place[from];
	s+=sum_in_tree(1,l,r);
	return s;
}
inline void change(int now,int x,int dat)
{
	int l=tree[now].l,r=tree[now].r;
	if (l==r)
	{
		tree[now].mx=tree[now].tot=dat;
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid)change(now<<1,x,dat);
	else change(now<<1|1,x,dat);
	update(now);
}
int main()
{
	//freopen("count.in","r",stdin);
	//freopen("count.out","w",stdout);
	n=read();
	for (int i=1;i<n;i++)
	  {
	  	int x=read(),y=read();
	  	insert(x,y);
	  }
	dfs1(1,1);
	for(int i=1;i<=n;i++)v[i]=read();
	dfs2(1,1);
	buildtree(1,1,n);
	m=read();
	for(int i=1;i<=m;i++)
	{
		scanf("%s",ch);
		int x,y;
		scanf("%d%d",&x,&y);
		lca=LCA(x,y);
		if (ch[1]=='M')printf("%d\n",max(ask(x,lca),ask(y,lca)));
		if (ch[1]=='S')printf("%d\n",sum(x,lca)+sum(y,lca)-v[lca]);
		if (ch[1]=='H')change(1,place[x],y),v[x]=y;
	}
	return 0;
}

  

posted on 2014-11-26 15:03  zhber  阅读(160)  评论(0编辑  收藏  举报