zoukankan      html  css  js  c++  java
  • 【BZOJ4372】烁烁的游戏 动态树分治+线段树

    【BZOJ4372】烁烁的游戏

    Description

    背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
    题意:
    给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
    烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
    烁烁很好奇,在当前时刻,节点u有多少个他的好朋友---皮皮鼠。
    大意:
    给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:
    Q x:询问x的点权。
    M x d w:将树上与节点x距离不超过d的节点的点权均加上w。

    Input

    第一行两个正整数:n,m
    接下来的n-1行,每行三个正整数u,v,代表u,v之间有一条边。
    接下来的m行,每行给出上述两种操作中的一种。

    Output

    对于每个Q操作,输出当前x节点的皮皮鼠数量。

    Sample Input

    7 6
    1 2
    1 4
    1 5
    2 3
    2 7
    5 6
    M 1 1 2
    Q 5
    M 2 2 3
    Q 3
    M 1 2 1
    Q 2

    Sample Output

    2
    3
    6

    HINT

    数据范围:
    n,m<=10^5,|w|<=10^4
    注意:w不一定为正整数,因为烁烁可能把皮皮鼠吓傻了。

    题解:动态点分治+线段树裸题,每个节点开两棵线段树维护它子树中的以及它的父亲要从它中减去的即可。

    注意特判边界的问题。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxn=100010;
    int n,m,tot,ans,cnt,mn,rt;
    struct sag
    {
    	int ls,rs,sum;
    }s[maxn*150];
    int to[maxn<<1],next[maxn<<1],head[maxn],siz[maxn],dep[maxn],pos[maxn],md[20][maxn<<1],fa[maxn],Log[maxn<<1];
    int r1[maxn],r2[maxn];
    bool vis[maxn];
    char str[5];
    inline void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void getrt(int x,int fa)
    {
    	int i,tmp=0;
    	siz[x]=1;
    	for(i=head[x];i!=-1;i=next[i])	if(!vis[to[i]]&&to[i]!=fa)	getrt(to[i],x),siz[x]+=siz[to[i]],tmp=max(tmp,siz[to[i]]);
    	tmp=max(tmp,tot-siz[x]);
    	if(tmp<mn)	mn=tmp,rt=x;
    }
    void solve(int x)
    {
    	vis[x]=1;
    	for(int i=head[x];i!=-1;i=next[i])	if(!vis[to[i]])
    		tot=siz[to[i]],mn=1<<30,getrt(to[i],x),fa[rt]=x,solve(rt);
    }
    void dfs(int x,int fa)
    {
    	md[0][++pos[0]]=dep[x],pos[x]=pos[0];
    	for(int i=head[x];i!=-1;i=next[i])	if(to[i]!=fa)
    		dep[to[i]]=dep[x]+1,dfs(to[i],x),md[0][++pos[0]]=dep[x];
    }
    inline int getmin(int a,int b)
    {
    	a=pos[a],b=pos[b];
    	if(a>b)	swap(a,b);
    	int k=Log[b-a+1];
    	return min(md[k][a],md[k][b-(1<<k)+1]);
    }
    inline int dis(int a,int b)
    {
    	return dep[a]+dep[b]-2*getmin(a,b);
    }
    void updata(int l,int r,int &x,int a,int b)
    {
    	if(a<0)	return ;
    	if(!x)	x=++tot;
    	s[x].sum+=b;
    	if(l==r)	return ;
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,s[x].ls,a,b);
    	else	updata(mid+1,r,s[x].rs,a,b);
    }
    int query(int l,int r,int x,int a,int b)
    {
    	if(!x||(a<=l&&r<=b))	return s[x].sum;
    	int mid=(l+r)>>1;
    	if(b<=mid)	return	query(l,mid,s[x].ls,a,b);
    	if(a>mid)	return	query(mid+1,r,s[x].rs,a,b);
    	return query(l,mid,s[x].ls,a,b)+query(mid+1,r,s[x].rs,a,b);
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,j,x,y,a,b,u;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<n;i++)	a=rd(),b=rd(),add(a,b),add(b,a);
    	dfs(1,0),tot=n,mn=1<<30,getrt(1,0),solve(rt),tot=0;
    	for(j=1;(1<<j)<=2*n-1;j++)	for(i=1;i+(1<<j)-1<=2*n-1;i++)	md[j][i]=min(md[j-1][i],md[j-1][i+(1<<(j-1))]);
    	for(i=2;i<=2*n-1;i++)	Log[i]=Log[i>>1]+1;
    	for(i=1;i<=m;i++)
    	{
    		scanf("%s",str);
    		if(str[0]=='Q')
    		{
    			u=rd(),ans=0;
    			for(x=u;x;x=y)
    			{
    				y=fa[x];
    				ans+=query(0,n,r1[x],dis(u,x),n);
    				if(y)	ans-=query(0,n,r2[x],dis(u,y),n);
    			}
    			printf("%d
    ",ans);
    		}
    		else
    		{
    			u=rd(),a=rd(),b=rd();
    			for(x=u;x;x=y)
    			{
    				y=fa[x];
    				updata(0,n,r1[x],min(n,a-dis(u,x)),b);
    				if(y)	updata(0,n,r2[x],min(n,a-dis(u,y)),b);
    			}
    		}
    	}
    	return 0;
    }//7 2 1 2 1 4 1 5 2 3 2 7 5 6 M 1 2 1 Q 2
  • 相关阅读:
    使用EF进行简单的增删改查
    观察者模式(委托事件的小应用)
    lambda表达式和表达式树
    socket知识总结
    xml读写Demo
    winfrom DataGridView Demo
    6月26号.NET面试题(程序题部分)只要做懂这3道题肯定能脱离菜鸟称号!
    多线程与异步编程知识简单总结
    15年6月14号面试中没有回答出来的问题
    2020.5.15记一次阿里电话面试经历
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7965538.html
Copyright © 2011-2022 走看看