• 【ZJOI2008】树的统计


    题目

    一棵树上有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本身

    分析

    只用单点修改的树链剖分模板题。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    using namespace std;
    struct trees
    {
    	int v,mx,l,r;
    }tree[90000];
    int d[90000],dson[90000],deep[90000],size[90000],fa[90000],top[90000],n,m,v[90000],bef[90000],tot,mi2[30];
    int next[90000],last[90000],to[90000],po;
    int ans;
    int bj(int x,int y)
    {
    	next[++tot]=last[x];
    	last[x]=tot;
    	to[tot]=y;
    }
    int dg(int x)
    {
    	size[x]=1;
    	int mx=0;
    	for(int i=last[x];i;i=next[i])
    	{
    		if(to[i]!=fa[x])
    		{
    			fa[to[i]]=x;
    			deep[to[i]]=deep[x]+1;
    			dg(to[i]);
    			size[x]+=size[to[i]];
    			if(size[to[i]]>mx)
    			{
    				mx=size[to[i]];
    				dson[x]=to[i];
    			}
    		}
    	}
    }
    int dg1(int x)
    {
    	bef[x]=++tot;
    	d[tot]=x;
    	if(top[x]==0)
    	{
    		top[x]=x;
    	}
    	if(dson[x])
    	{
    		top[dson[x]]=top[x];
    		dg1(dson[x]);
    	}
    	for(int i=last[x];i;i=next[i])
    	{
    		if(to[i]!=fa[x] && to[i]!=dson[x])
    		{
    			dg1(to[i]);
    		}
    	}
    }
    int treechange(int l,int r,int pos,int aim,int value)
    {
    	int mid=(l+r)/2;
    	tree[pos].l=l;
    	tree[pos].r=r;
    	if(l==r)
    	{
    		tree[pos].v=value;
    		tree[pos].mx=value;
    		return 0;
    	}
    	if(aim<=mid)
    	{
    		treechange(l,mid,pos*2,aim,value);
    	}
    	else
    	{
    		treechange(mid+1,r,pos*2+1,aim,value);
    	}
    	tree[pos].v=tree[pos*2].v+tree[pos*2+1].v;
    	tree[pos].mx=max(tree[pos*2].mx,tree[pos*2+1].mx);
    }
    int findmx(int l,int r,int pos,int aiml,int aimr)
    {
    	int mid=(l+r)/2;
    	if(l==aiml && r==aimr)
    	{
    		ans=max(ans,tree[pos].mx);
    		return 0;
    	}
    	if(aimr<=mid)
    	{
    		findmx(l,mid,pos*2,aiml,aimr);
    	}
    	else
    	if(aiml>mid)
    	{
    		findmx(mid+1,r,pos*2+1,aiml,aimr);
    	}
    	else
    	{
    		findmx(l,mid,pos*2,aiml,mid);
    		findmx(mid+1,r,pos*2+1,mid+1,aimr);
    	}
    }
    int findmax(int x,int y)
    {
    	ans=-maxlongint;
    	while(top[x]!=top[y])
    	{
    		if(deep[top[x]]>=deep[top[y]])
    		{
    			findmx(1,n,1,bef[top[x]],bef[x]);
    			x=fa[top[x]];
    		}
    		else
    		{
    			findmx(1,n,1,bef[top[y]],bef[y]);
    			y=fa[top[y]];
    		}
    	}
    	if(deep[x]>=deep[y])
    	{
    		findmx(1,n,1,bef[y],bef[x]);
    	}
    	else
    	{
    		findmx(1,n,1,bef[x],bef[y]);
    	}
    	printf("%d
    ",ans);
    }
    int findsm(int l,int r,int pos,int aiml,int aimr)
    {
    	int mid=(l+r)/2;
    	if(l==aiml && r==aimr)
    	{
    		ans+=tree[pos].v;
    		return 0;
    	}
    	if(aimr<=mid)
    	{
    		findsm(l,mid,pos*2,aiml,aimr);
    	}
    	else
    	if(aiml>mid)
    	{
    		findsm(mid+1,r,pos*2+1,aiml,aimr);
    	}
    	else
    	{
    		findsm(l,mid,pos*2,aiml,mid);
    		findsm(mid+1,r,pos*2+1,mid+1,aimr);
    	}
    }
    int findsum(int x,int y)
    {
    	ans=0;
    	while(top[x]!=top[y])
    	{
    		if(deep[top[x]]>=deep[top[y]])
    		{
    			findsm(1,n,1,bef[top[x]],bef[x]);
    			x=fa[top[x]];
    		}
    		else
    		{
    			findsm(1,n,1,bef[top[y]],bef[y]);
    			y=fa[top[y]];
    		}
    	}
    	if(deep[x]>=deep[y])
    	{
    		findsm(1,n,1,bef[y],bef[x]);
    	}
    	else
    	{
    		findsm(1,n,1,bef[x],bef[y]);
    	}
    	printf("%d
    ",ans);
    }
    int main()
    {
    	mi2[1]=1;
    	for(int i=2;i<=25;i++)
    		mi2[i]=mi2[i-1]*2;
    	scanf("%d",&n);
    	for(int i=1;i<=n-1;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		bj(x,y);
    		bj(y,x);
    	}
    	deep[1]=1;
    	dg(1);
    	tot=0;
    	dg1(1);
    	for(int i=1;i<=90000-1;i++)
    		tree[i].mx=-maxlongint;
    	for(int i=1;i<=25;i++)
    	{
    		if(mi2[i]*2>=tot)
    		{
    			po=mi2[i]*2-1;
    			break;
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		int x;
    		scanf("%d",&x);
    		treechange(1,n,1,bef[i],x);
    	}
    	scanf("%d
    ",&m);
    	char c;
    	for(int i=1;i<=m;i++)
    	{
    		c=getchar();
    		if(c=='C')
    		{
    			int x,y;
    			scanf("HANGE %d %d
    ",&x,&y);
    			treechange(1,n,1,bef[x],y);
    		}
    		else
    		{
    			c=getchar();
    			if(c=='M')
    			{
    				int x,y;
    				scanf("AX %d %d
    ",&x,&y);
    				findmax(x,y);
    			}
    			else
    			{
    				int x,y;
    				scanf("UM %d %d
    ",&x,&y);
    				findsum(x,y);
    			}
    		}
    		
    	}
    }
    
  • 相关阅读:
    【并查集】hdu 1198 Farm Irrigation
    【并查集】hdu 1325 Is It A Tree?
    【并查集】hdu 1272 小希的迷宫
    【并查集】hdu 1856 More is better
    【并查集】hdu 3635 Dragon Balls
    【并查集】poj 1988 Cube Stacking
    【并查集】poj 2492 A Bug's Life(二集合问题)
    【并查集】poj 2236 Wireless Network
    【并查集】poj 1703 Find them, Catch them(二集合问题)
    【并查集】poj 1611 The Suspects
  • 原文地址:https://www.cnblogs.com/chen1352/p/9026690.html
Copyright © 2020-2023  润新知