• 【BZOJ3999】【TJOI2015】旅游 树剖


    题目大意

      给你一棵树,有(n)个点。有(q)个操作,每次要你从(x)(y)的路径上选两个点,使得距离(x)比较远的点的点权(-)距离(x)比较近的点的点权最大,然后把这条路径上所有点的点权(+v)

      (n,qleq 50000)

    题解

      这种题没什么意思,直接树剖就好了。

      线段树上每个点记录最大值,最小值,从左往右走和从右往左走的最大收益。

      时间复杂度:(O(n+qlog^2 n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<cmath>
    #include<functional>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> pll;
    void sort(int &a,int &b)
    {
    	if(a>b)
    		swap(a,b);
    }
    void open(const char *s)
    {
    #ifndef ONLINE_JUDGE
    	char str[100];
    	sprintf(str,"%s.in",s);
    	freopen(str,"r",stdin);
    	sprintf(str,"%s.out",s);
    	freopen(str,"w",stdout);
    #endif
    }
    int rd()
    {
    	int s=0,c;
    	while((c=getchar())<'0'||c>'9');
    	do
    	{
    		s=s*10+c-'0';
    	}
    	while((c=getchar())>='0'&&c<='9');
    	return s;
    }
    int upmin(int &a,int b)
    {
    	if(b<a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    int upmax(int &a,int b)
    {
    	if(b>a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    struct pp
    {
    	ll ma,mi;
    	ll s1,s2;
    	pp()
    	{
    		ma=mi=s1=s2=0;
    	}
    };
    pp merge(pp a,pp b)
    {
    	pp c;
    	c.s1=max(b.ma-a.mi,max(a.s1,b.s1));
    	c.s2=max(a.ma-b.mi,max(a.s2,b.s2));
    	c.ma=max(a.ma,b.ma);
    	c.mi=min(a.mi,b.mi);
    	return c;
    }
    pp rev(pp a)
    {
    	swap(a.s1,a.s2);
    	return a;
    }
    int c[100010];
    namespace seg
    {
    	struct tree
    	{
    		int ls,rs;
    		int l,r;
    		ll t;
    		pp s;
    	};
    	tree a[100010];
    	int cnt;
    	void build(int &p,int l,int r)
    	{
    		p=++cnt;
    		a[p].l=l;
    		a[p].r=r;
    		if(l==r)
    		{
    			a[p].s.ma=a[p].s.mi=c[l];
    			return;
    		}
    		int mid=(l+r)>>1;
    		build(a[p].ls,l,mid);
    		build(a[p].rs,mid+1,r);
    		a[p].s=merge(a[a[p].ls].s,a[a[p].rs].s);
    	}
    	void add(int p,ll v)
    	{
    		a[p].s.ma+=v;
    		a[p].s.mi+=v;
    		a[p].t+=v;
    	}
    	void push(int p)
    	{
    		if(a[p].t&&a[p].ls!=a[p].r)
    		{
    			add(a[p].ls,a[p].t);
    			add(a[p].rs,a[p].t);
    			a[p].t=0;
    		}
    	}
    	void add(int p,int l,int r,int v)
    	{
    		if(l<=a[p].l&&r>=a[p].r)
    		{
    			add(p,v);
    			return;
    		}
    		push(p);
    		int mid=(a[p].l+a[p].r)>>1;
    		if(l<=mid)
    			add(a[p].ls,l,r,v);
    		if(r>mid)
    			add(a[p].rs,l,r,v);
    		a[p].s=merge(a[a[p].ls].s,a[a[p].rs].s);
    	}
    	pp query(int p,int l,int r)
    	{
    		if(l<=a[p].l&&r>=a[p].r)
    			return a[p].s;
    		push(p);
    		int mid=(a[p].l+a[p].r)>>1;
    		if(r<=mid)
    			return query(a[p].ls,l,r);
    		if(l>mid)
    			return query(a[p].rs,l,r);
    		return merge(query(a[p].ls,l,r),query(a[p].rs,l,r));
    	}
    }
    struct graph
    {
    	int v[100010];
    	int t[100010];
    	int h[50010];
    	int n;
    	graph()
    	{
    		n=0;
    	}
    	void add(int x,int y)
    	{
    		n++;
    		v[n]=y;
    		t[n]=h[x];
    		h[x]=n;
    	}
    };
    graph g;
    struct p
    {
    	int f,w,t,d,ms,s;
    };
    p a[100010];
    int wcnt;
    void dfs1(int x,int fa,int dep)
    {
    	a[x].f=fa;
    	a[x].d=dep;
    	a[x].s=1;
    	int ms=0;
    	int i;
    	for(i=g.h[x];i;i=g.t[i])
    		if(g.v[i]!=fa)
    		{
    			dfs1(g.v[i],x,dep+1);
    			if(a[g.v[i]].s>ms)
    			{
    				ms=a[g.v[i]].s;
    				a[x].ms=g.v[i];
    			}
    			a[x].s+=a[g.v[i]].s;
    		}
    }
    void dfs2(int x,int top)
    {
    	a[x].w=++wcnt;
    	a[x].t=top;
    	if(!a[x].ms)
    		return;
    	dfs2(a[x].ms,top);
    	int i;
    	for(i=g.h[x];i;i=g.t[i])
    		if(g.v[i]!=a[x].f&&g.v[i]!=a[x].ms)
    			dfs2(g.v[i],g.v[i]);
    }
    int prize[100010];
    int rt;
    ll query(int x,int y,int z)
    {
    	pp s1,s2;
    	s1.ma=s1.mi=0x7fffffff;
    	s2.ma=s2.mi=-0x7fffffff;
    	while(a[x].t!=a[y].t)
    		if(a[a[x].t].d>a[a[y].t].d)
    		{
    			s1=merge(s1,rev(seg::query(rt,a[a[x].t].w,a[x].w)));
    			seg::add(rt,a[a[x].t].w,a[x].w,z);
    			x=a[a[x].t].f;
    		}
    		else
    		{
    			s2=merge(seg::query(rt,a[a[y].t].w,a[y].w),s2);
    			seg::add(rt,a[a[y].t].w,a[y].w,z);
    			y=a[a[y].t].f;
    		}
    	if(a[x].w<a[y].w)
    	{
    		s2=merge(seg::query(rt,a[x].w,a[y].w),s2);
    		seg::add(rt,a[x].w,a[y].w,z);
    	}
    	else
    	{
    		s1=merge(s1,rev(seg::query(rt,a[y].w,a[x].w)));
    		seg::add(rt,a[y].w,a[x].w,z);
    	}
    	s1=merge(s1,s2);
    	return s1.s1;
    }
    int main()
    {
    	open("bzoj3999");
    	int n,q;
    	scanf("%d",&n);
    	int i,x,y,z;
    	for(i=1;i<=n;i++)
    		scanf("%d",&prize[i]);
    	for(i=1;i<n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		g.add(x,y);
    		g.add(y,x);
    	}
    	dfs1(1,0,1);
    	dfs2(1,1);
    	for(i=1;i<=n;i++)
    		c[a[i].w]=prize[i];
    	seg::build(rt,1,n);
    	scanf("%d",&q);
    	for(i=1;i<=q;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		ll ans=query(x,y,z);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    JDBCUtils
    C3P0配置
    反射基本常识(二)
    反射基本常识(一)
    String to Integer (atoi)
    ZigZag Conversion
    Longest Palindromic Substring
    Palindrome Number
    Reverse Integer
    Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513421.html
Copyright © 2020-2023  润新知