• 【BZOJ3730】震波(动态点分治)


    【BZOJ3730】震波(动态点分治)

    题面

    BZOJ
    题意
    给定一棵树,
    每次询问到一个点的距离(<=K)的点的权值之和
    动态修改权值,
    强制在线

    题解

    正常的(DP)???
    很简单呀。
    每次暴力往父亲跳,不断的加值,
    然后容斥一下就行了

    现在要动态维护
    就维护一下动态点分治

    但是现在记录起来没那么容易了
    于是开两棵线段树
    每次做一下差
    不断暴跳点分树的父亲就行啦

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 120000
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    struct Line{int v,next,w,rt;}e[MAX<<1],E[MAX<<1];
    int h[MAX],cnt=1;
    inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w,0};h[u]=cnt++;}
    /************************************************************************/
    int dfn[MAX],top[MAX],dep[MAX],ssize[MAX],hson[MAX],fa[MAX];
    int dis[MAX];
    void dfs1(int u,int ff)
    {
    	fa[u]=ff;ssize[u]=1;dep[u]=dep[ff]+1;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(v==ff)continue;
    		dis[v]=dis[u]+e[i].w;
    		dfs1(v,u);
    		ssize[u]+=ssize[v];
    		if(ssize[hson[u]]<ssize[v])hson[u]=v;
    	}
    }
    void dfs2(int u,int tp)
    {
    	top[u]=tp;
    	if(hson[u])dfs2(hson[u],tp);
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(v==fa[u]||v==hson[u])continue;
    		dfs2(v,v);
    	}
    }
    int LCA(int u,int v)
    {
    	while(top[u]!=top[v])
    	{
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		u=fa[top[u]];
    	}
    	return dep[u]<dep[v]?u:v;
    }
    int Dis(int u,int v)
    {
    	return dis[u]+dis[v]-dis[LCA(u,v)]*2;
    }
    /************************************************************************/
    int sum[MAX],size[MAX],Fa[MAX];
    int n,Q,m,val[MAX];
    int Size,root,minr;
    bool vis[MAX];
    void Getroot(int u,int ff)
    {
    	size[u]=1;
    	int ret=0;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(v==ff||vis[v])continue;
    		Getroot(v,u);
    		size[u]+=size[v];
    		ret=max(ret,size[v]);
    	}
    	ret=max(ret,Size-size[u]);
    	if(ret<minr)minr=ret,root=u;
    }
    void DFS(int u,int ff)
    {
    	vis[u]=true;Fa[u]=ff;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(vis[v])continue;
    		minr=n;Size=size[v];
    		Getroot(v,u);
    		DFS(root,u);
    	}
    }
    struct Node
    {
    	int ls,rs;
    	int v;
    }t[MAX*150];
    int tot,rt[MAX<<1];
    void Modify(int &now,int l,int r,int pos,int w)
    {
    	if(!now)now=++tot;t[now].v+=w;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(pos<=mid)Modify(t[now].ls,l,mid,pos,w);
    	else Modify(t[now].rs,mid+1,r,pos,w);
    }
    int Query(int now,int l,int r,int L,int R)
    {
    	if(!now)return 0;
    	if(L<=l&&r<=R)return t[now].v;
    	int ret=0,mid=(l+r)>>1;
    	if(L<=mid)ret+=Query(t[now].ls,l,mid,L,R);
    	if(R>mid)ret+=Query(t[now].rs,mid+1,r,L,R);
    	return ret;
    }
    void PModify(int u,int w)
    {
    	Modify(rt[u],0,n,0,w);
    	for(int i=u;Fa[i];i=Fa[i])
    	{
    		int dist=Dis(u,Fa[i]);
    		Modify(rt[Fa[i]],0,n,dist,w);
    		Modify(rt[i+n],0,n,dist,w);
    	}
    }
    int PQuery(int u,int K)
    {
    	int ret=Query(rt[u],0,n,0,K);
    	for(int i=u;Fa[i];i=Fa[i])
    	{
    		int dist=Dis(u,Fa[i]);
    		if(dist>K)continue;
    		ret+=Query(rt[Fa[i]],0,n,0,K-dist);
    		ret-=Query(rt[i+n],0,n,0,K-dist);
    	}
    	return ret;
    }
    int main()
    {
    	n=read();Q=read();
    	for(int i=1;i<=n;++i)val[i]=read();
    	for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v,1),Add(v,u,1);
    	dfs1(1,0);dfs2(1,1);
    	minr=Size=n;Getroot(1,0);
    	DFS(root,0);
    	for(int i=1;i<=n;++i)PModify(i,val[i]);
    	int ans=0;
    	while(Q--)
    	{
    		int opt=read();
    		if(opt)
    		{
    			int u=read()^ans,v=read()^ans;
    			PModify(u,v-val[u]);
    			val[u]=v;
    		}
    		else
    		{
    			int u=read()^ans,K=read()^ans;
    			ans=PQuery(u,K);
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    平凡人生的忠告
    Visio建模
    2007的第一天....
    PowerDesigner12对SQL2005反向工程问题.
    强人画的画:)
    2006的最后一天
    ASP.NET生成树形显示的GridView
    输出由1~9组成和三组三位数,第二组是第一组的2倍,第三组是第一组的3倍,三组数字中无重复数字
    C#读取图片Exif信息
    C#读取数据库图片显示、缩小、更新
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8279311.html
Copyright © 2020-2023  润新知