• 【BZOJ3626】LCA(树链剖分,Link-Cut Tree)


    【BZOJ3626】LCA(树链剖分,Link-Cut Tree)

    题面

    Description

    给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
    设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
    有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
    (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    Input

    第一行2个整数n q。
    接下来n-1行,分别表示点1到点n-1的父节点编号。
    接下来q行,每行3个整数l r z。

    Output

    输出q行,每行表示一个询问的答案。每个答案对201314取模输出

    Sample Input

    5 2

    0

    0

    1

    1

    1 4 3

    1 4 2

    Sample Output

    8

    5

    HINT

    共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

    题解

    我不会做的一道神题
    OrzZsyDalao,看一眼就会做

    如果暴力求,,,还是挺好的呀

    咳咳,看正解
    画画图
    对于区间L~R,把每个点到根节点的路径全部+1
    此时累加Z到根节点的路径权值和,发现就是答案

    为啥呢
    首先,我们可以知道LCA一定在Z到根节点的路径上
    其次,深度就是LCA到根节点的路径长度
    如果像上面那样计算,因为整个路径上都加了1
    相当于加了整个LCA的深度
    因此这样做就是对的

    所以,直接离线处理就好了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define lson (t[x].ch[0])
    #define rson (t[x].ch[1])
    #define MAX 100000
    #define MOD 201314
    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 Node
    {
    	int ch[2],ff;
    	int rev,pls;
    	int size,sum,v;
    }t[MAX];
    int S[MAX],top,n,Q;
    bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
    void pushup(int x)
    {
    	t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;
    	t[x].sum=(t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+t[x].v)%MOD;
    }
    void Reverse(int x){swap(lson,rson);t[x].rev^=1;}
    void pushdown(int x)
    {
    	if(t[x].rev)
    	{
    		if(lson)Reverse(lson);
    		if(rson)Reverse(rson);
    		t[x].rev^=1;
    	}
    	if(t[x].pls)
    	{
    		if(lson)
    		{
    			(t[lson].v+=t[x].pls)%=MOD;
    			(t[lson].sum+=t[x].pls*t[lson].size%MOD)%=MOD;
    			t[lson].pls=(t[lson].pls+t[x].pls)%MOD;
    		}
    		if(rson)
    		{
    			(t[rson].v+=t[x].pls)%=MOD;
    			(t[rson].sum+=t[x].pls*t[rson].size%MOD)%=MOD;
    			t[rson].pls=(t[rson].pls+t[x].pls)%MOD;
    		}
    		t[x].pls=0;
    	}
    }
    void rotate(int x)
    {
        int y=t[x].ff,z=t[y].ff;
        int k=t[y].ch[1]==x;
        if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
        t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
        t[x].ch[k^1]=y;t[y].ff=x;
        pushup(y);pushup(x);
    }
    void Splay(int x)
    {
        S[top=1]=x;
        for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
        while(top)pushdown(S[top--]);
        while(!isroot(x))
        {
            int y=t[x].ff,z=t[y].ff;
            if(!isroot(y))
                (t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),t[x].ch[1]=y,pushup(x);}
    void makeroot(int x){access(x);Splay(x);Reverse(x);}
    void split(int x,int y){makeroot(x);access(y);Splay(y);}
    void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;pushup(y);}
    void link(int x,int y){makeroot(x);t[x].ff=y;}
    struct Ask
    {
    	int id,z,i,opt;
    }q[MAX*2];
    bool cmp(Ask a,Ask b){return a.i<b.i;}
    int ans[MAX],tot;
    int main()
    {
    	n=read();Q=read();
    	for(int i=2;i<=n;++i)
    	{
    		int u=read()+1;
    		link(i,u);
    	}
    	for(int i=1;i<=Q;++i)
    	{
    		int l=read(),r=read()+1,z=read()+1;
    		++tot;q[tot].id=q[tot+1].id=i;
    		q[tot].z=q[tot+1].z=z;
    		q[tot].i=l;q[tot+1].i=r;
    		q[tot].opt=-1;q[++tot].opt=1;
    	}
    	sort(&q[1],&q[tot+1],cmp);
    	int pos=1;
    	while(!q[pos].i&&pos<tot)++pos;
    	for(int i=1;i<=n;++i)
    	{
    		split(i,1);
    		t[1].v=(t[1].v+1)%MOD;
    		t[1].sum=(t[1].sum+t[1].size)%MOD;
    		t[1].pls=(t[1].pls+1)%MOD;
    		while(q[pos].i==i&&pos<=tot)
    		{
    			split(q[pos].z,1);
    			ans[q[pos].id]=(ans[q[pos].id]+q[pos].opt*t[1].sum%MOD+MOD)%MOD;
    			++pos;
    		}
    	}
    	for(int i=1;i<=Q;++i)printf("%d
    ",ans[i]%MOD);
    	return 0;
    }
    
    
  • 相关阅读:
    css选择器
    HTML标签用法
    pyenv python 版本控制
    Django之路
    Day15-Django
    python+selenium实现登录账户
    requests and BeautifulSoup
    清除MAC 可清除空间
    将python源文件打包成exe文件
    swift的一些东西
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8159109.html
Copyright © 2020-2023  润新知