BZOJ 2157: 旅游 树链剖分

Fancy posted @ 2015年7月04日 21:44 in BZOJ , 480 阅读

题目大意:更改桥上的愉悦度,求路径上的最大、最小、总愉悦度。

 

看完数据我疯了。。。自己造了个小数据。。。

维护边权的树链剖分,边的编号为下面一个点的编号

注意点是从0开始,所以我把点都加1了,其实直接写应该也可以

Min Max Sum函数中如果x和y相等的话要返回inf  -inf  0,才开始没写,改了好长时间。。。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int inf=20000001;
const int N=20010;
struct abcd  { int a,b,c; } v[N];
struct TREE  { int lc,rc,l,r,sum,max,min; } tree[N*4];
vector<int> to[N*2];
char s[4];
int n,m,totw,tot=1;
int vis[N],dep[N],fa[N],son[N],siz[N],top[N],w[N],val[N];
void DFS(int x)
{
	int t=0;
	vis[x]=1;dep[x]=dep[fa[x]]+1;
	for(int i=0;i<to[x].size();i++)
	{
		int y=to[x][i];
		if(!vis[y])
		{
			t=1;
			fa[y]=x;DFS(y);siz[x]+=siz[y];
			if(siz[y]>siz[son[x]]) son[x]=y;
		}
	}
}
void DFS2(int x)
{
	if(son[x]) 
	{
		top[son[x]]=top[x];
	    w[son[x]]=++totw;
	    DFS2(son[x]);
	}
	for(int i=0;i<to[x].size();i++)
	{
		int y=to[x][i];
		if(y!=fa[x]&&y!=son[x])
		{
			top[y]=y;
			w[y]=++totw;
			DFS2(y);
		}
	}
}
void build(int x,int l,int r)
{
	tree[x].l=l;tree[x].r=r;
	if(r==l)
	{
		tree[x].sum=val[l];tree[x].max=val[l];tree[x].min=val[l];
		return;
	}
	int mid=(l+r)/2;
	tree[x].lc=++tot; build(tree[x].lc,l,mid);
	tree[x].rc=++tot; build(tree[x].rc,mid+1,r);
	tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum;
	tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max);
	tree[x].min=min(tree[tree[x].lc].min,tree[tree[x].rc].min);
}
void change(int x,int v,int d)
{
	if(tree[x].l==tree[x].r)
	{
		tree[x].sum=d;tree[x].max=d;tree[x].min=d;
		return;
	}
	int mid=(tree[x].l+tree[x].r)/2;
	if(v<=mid) change(tree[x].lc,v,d);
	else change(tree[x].rc,v,d);
	tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum;
	tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max);
	tree[x].min=min(tree[tree[x].lc].min,tree[tree[x].rc].min);
}
void changefan(int x,int v)
{
	if(tree[x].l==tree[x].r)
	{
		int d=-tree[x].sum;
		tree[x].sum=d;tree[x].max=d;tree[x].min=d;
		return;
	}
	int mid=(tree[x].l+tree[x].r)/2;
	if(v<=mid) changefan(tree[x].lc,v);
	else changefan(tree[x].rc,v);
	tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum;
	tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max);
	tree[x].min=min(tree[tree[x].lc].min,tree[tree[x].rc].min);
}
void Fan(int x,int y)
{
	int f1=top[x],f2=top[y];
	if(f1!=f2)
	{
		if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
		while(x!=fa[f1]) changefan(1,w[x]),x=fa[x];
		return Fan(fa[f1],y);
	}
	else 
	{
		if(dep[x]<dep[y]) swap(x,y);
		while(x!=y) changefan(1,w[x]),x=fa[x];
	}
}
int querysum(int x,int l,int r)
{
	if(l>r) swap(l,r);
	if(l<=tree[x].l&&tree[x].r<=r) return tree[x].sum;
	int mid=(tree[x].l+tree[x].r)/2;
	int ans=0;
	if(l<=mid) ans+=querysum(tree[x].lc,l,r);
	if(mid<r)  ans+=querysum(tree[x].rc,l,r);
	return ans;
}
int Sum(int x,int y)
{
	if(x==y) return 0;
	int f1=top[x],f2=top[y];
	if(f1!=f2)
	{
		if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
		return querysum(1,w[f1],w[x])+Sum(fa[f1],y);
	}
	else 
	{
		if(x>y) swap(x,y);
		return querysum(1,w[x]+1,w[y]);
	}
}
int querymax(int x,int l,int r)
{
	if(l>r) swap(l,r);
	if(l<=tree[x].l&&tree[x].r<=r) return tree[x].max;
	int mid=(tree[x].l+tree[x].r)/2;
	int ans=-inf;
	if(l<=mid) ans=max(ans,querymax(tree[x].lc,l,r));
	if(mid<r)  ans=max(ans,querymax(tree[x].rc,l,r));
	return ans;
}
int Max(int x,int y)
{
	if(x==y) return -inf;
	int f1=top[x],f2=top[y];
	if(f1!=f2)
	{
		if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
		return max(querymax(1,w[f1],w[x]),Max(fa[f1],y));
	}
	else 
	{
		if(x>y) swap(x,y);
		return querymax(1,w[x]+1,w[y]);
	}
}
int querymin(int x,int l,int r)
{
	if(l>r) swap(l,r);
	if(l<=tree[x].l&&tree[x].r<=r) return tree[x].min;
	int mid=(tree[x].l+tree[x].r)/2;
	int ans=inf;
	if(l<=mid) ans=min(ans,querymin(tree[x].lc,l,r));
	if(mid<r)  ans=min(ans,querymin(tree[x].rc,l,r));
	return ans;
}
int Min(int x,int y)
{
	if(x==y) return inf;
	int f1=top[x],f2=top[y];
	if(f1!=f2)
	{
		if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
		return min(querymin(1,w[f1],w[x]),Min(fa[f1],y));
	}
	else 
	{
		if(x>y) swap(x,y);
		return querymin(1,w[x]+1,w[y]);
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d%d",&v[i].a,&v[i].b,&v[i].c);
		v[i].a++;v[i].b++;
		to[v[i].a].push_back(v[i].b);
		to[v[i].b].push_back(v[i].a);
	}
	for(int i=1;i<=n;i++) siz[i]=1;
	DFS(1);
	top[1]=1;DFS2(1);
	for(int i=1;i<n;i++)
	{
		if(v[i].a<v[i].b) swap(v[i].a,v[i].b);
		val[w[v[i].a]]=v[i].c;
	}
	build(1,1,n-1);
	scanf("%d",&m);
	for(int i=1,x,y;i<=m;i++)
	{
		scanf("%s",s);
		scanf("%d%d",&x,&y);
		if(s[0]=='C')
			change(1,w[v[x].a],y);
		else if(s[0]=='N')
		    Fan(x+1,y+1);
		else if(s[0]=='S')
            printf("%d\n",Sum(x+1,y+1));
        else if(s[0]=='M'&&s[1]=='A')
            printf("%d\n",Max(x+1,y+1));
        else printf("%d\n",Min(x+1,y+1));
	}
}

 

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter