zoukankan      html  css  js  c++  java
  • 【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);
    			}
    		}
    		
    	}
    }
    
  • 相关阅读:
    【leetcode】1215.Stepping Numbers
    【leetcode】1214.Two Sum BSTs
    【leetcode】1213.Intersection of Three Sorted Arrays
    【leetcode】1210. Minimum Moves to Reach Target with Rotations
    【leetcode】1209. Remove All Adjacent Duplicates in String II
    【leetcode】1208. Get Equal Substrings Within Budget
    【leetcode】1207. Unique Number of Occurrences
    【leetcode】689. Maximum Sum of 3 Non-Overlapping Subarrays
    【leetcode】LCP 3. Programmable Robot
    【leetcode】LCP 1. Guess Numbers
  • 原文地址:https://www.cnblogs.com/chen1352/p/9026690.html
Copyright © 2011-2022 走看看