• 长链剖分


    前言

    某道题要求树上 (k) 级祖先,然后我发现我不会长剖,学了一下,感觉会了重剖之后长剖很好理解。

    但是我为什么不会长剖呢?

    讲解

    先鸽着。

    练习

    板题(洛谷)

    代码

    板题(洛谷)
    //12252024832524
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 500005;
    int n,Q;
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    #define ui unsigned int
    ui S;
    
    inline ui Get() {
    	S ^= S << 13;
    	S ^= S >> 17;
    	S ^= S << 5;
    	return S; 
    }
    
    int head[MAXN],tot;
    struct edge
    {
    	int v,nxt;
    }e[MAXN];
    void Add_Edge(int x,int y)
    {
    	e[++tot].v = y;
    	e[tot].nxt = head[x];
    	head[x] = tot;
    }
    
    int f[MAXN][19],d[MAXN],LG[MAXN],rt,son[MAXN],MD[MAXN];
    void dfs1(int x)
    {
    	MD[x] = d[x] = d[f[x][0]] + 1;
    	for(int i = 1;i <= LG[d[x]];++ i) f[x][i] = f[f[x][i-1]][i-1];
    	for(int i = head[x]; i ;i = e[i].nxt)
    	{
    		dfs1(e[i].v);
    		MD[x] = Max(MD[x],MD[e[i].v]);
    		if(MD[e[i].v] > MD[son[x]]) son[x] = e[i].v;
    	}
    }
    int dfn[MAXN],dfntot,U[MAXN],D[MAXN],tp[MAXN];
    void dfs2(int x,int t) 
    {
    	if(x == t) tp[x] = x;
    	else tp[x] = tp[f[x][0]];
    	dfn[x] = ++dfntot;
    	U[dfntot] = t; D[dfntot] = x;
    	if(!son[x]) return;
    	dfs2(son[x],f[t][0]);
    	for(int i = head[x]; i ;i = e[i].nxt)
    		if(e[i].v^son[x])
    			dfs2(e[i].v,e[i].v);
    }
    int Query(int u,int k)
    {
    	if(!k) return u;
    	u = f[u][LG[k]]; k -= 1<<LG[k];
    	k -= d[u] - d[tp[u]]; u = tp[u];
    	if(k >= 0) return U[dfn[u]+k];
    	else return D[dfn[u]-k];
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); Q = Read(); S = Read();
    	LG[0] = -1;
    	for(int i = 1;i <= n;++ i) LG[i] = LG[i>>1] + 1;
    	for(int i = 1;i <= n;++ i)
    		if((f[i][0] = Read())) Add_Edge(f[i][0],i);
    		else rt = i;
    	dfs1(rt);
    	dfs2(rt,rt);
    	LL ans = 0,lst = 0;
    	for(int i = 1;i <= Q;++ i)
    	{
    		int u = (Get()^lst) % n + 1;
    		int k = (Get()^lst) % d[u];
    		lst = Query(u,k);
    		ans ^= lst * i;
    	}
    	Put(ans);
    	return 0;
    }
    
  • 相关阅读:
    spark RDD操作的底层实现原理
    Spark累加器(Accumulator)陷阱及解决办法
    spark collect获取所有元素
    spark submit 入门
    pyspark使用ipython
    top k
    快速排序
    用 Spark 为 Elasticsearch 导入搜索数据
    静态成员变量不占用类的内存空间
    重载函数的调用匹配规则
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15234040.html
Copyright © 2020-2023  润新知