• 【LNOI2014】LCA


    题面

    题解

    考察(dep[mathrm{LCA}(i, x)])的性质,发现它是(i)(x)的链交的长度。

    那么对每个(i)所在的链打一个区间加标记,询问时算一下(x)所在的链的区间和即可。

    如果有(l leq i leq r)的限制,就进行离线处理即可。

    代码

    好久之前的代码,有点丑见谅。

    #include<bits/stdc++.h>
    #define RG register
    #define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
    #define for_edge(i, x) for(RG int i=head[x];i;i=e[i].next)
    #define clear(x, y) memset(x, y, sizeof(x));
    using namespace std;
    
    template<typename T = int>
    inline T read()
    {
    	T data=0, w=1;
    	char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    	if(ch=='-') w=-1, ch=getchar();
    	while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+(ch^48), ch=getchar();
    	return data*w;
    }
    
    const int maxn(50010), mod(201314);
    struct edge { int next, to; } e[maxn];
    int head[maxn], e_num, n, q;
    inline void add_edge(int from, int to) { e[++e_num]={head[from], to}; head[from]=e_num; }
    int fa[maxn], heavy[maxn], size[maxn];
    void dfs(int x)
    {
    	size[x]=1;
    	int _max=0;
    	for_edge(i, x)
    	{
    		int to=e[i].to; dfs(to);
    		size[x]+=size[to];
    		if(size[to]>_max) _max=size[to], heavy[x]=to;
    	}
    }
    int pos[maxn], belong[maxn], cnt_node;
    void dfs(int x, int chain)
    {
    	pos[x]=++cnt_node;
    	belong[x]=chain;
    	int k=heavy[x];
    	if(!k) return;
    	dfs(k, chain);
    	for_edge(i, x)
    	{
    		int to=e[i].to;
    		if(to==k) continue;
    		dfs(to, to);
    	}
    }
    int sum[maxn<<2], lazy[maxn<<2];
    #define son(i) ((root<<1)|i)
    inline void pushdown(int root, int l, int r)
    {
    	if(l==r) lazy[root]=0;
    	if(!lazy[root]) return;
    	int mid(l+r>>1);
    	sum[son(0)]+=(mid-l+1)*lazy[root];
    	sum[son(1)]+=(r-mid)*lazy[root];
    	lazy[son(0)]+=lazy[root];
    	lazy[son(1)]+=lazy[root];
    	lazy[root]=0;
    }
    inline void update(int l, int r, int root=1, int nl=1, int nr=cnt_node)
    {
    	if(nr<l || nl>r) return;
    	if(l<=nl && nr<=r)
    	{
    		sum[root]+=nr-nl+1;
    		lazy[root]++;
    		return;
    	}
    	int mid(nl+nr>>1);
    	pushdown(root, nl, nr);
    	update(l, r, son(0), nl, mid); update(l, r, son(1), mid+1, nr);
    	sum[root]=sum[son(0)]+sum[son(1)];
    }
    inline void update_chain(int x) { while(x) update(pos[belong[x]], pos[x]), x=fa[belong[x]]; }
    inline int query(int l, int r, int root=1, int nl=1, int nr=cnt_node)
    {
    	if(nr<l || nl>r) return 0;
    	if(l<=nl && nr<=r) return sum[root];
    	int mid(nl+nr>>1);
    	pushdown(root, nl, nr);
    	return query(l, r, son(0), nl, mid)+query(l, r, son(1), mid+1, nr);
    }
    inline int query_chain(int x)
    {
    	int ans=0;
    	while(x) ans+=query(pos[belong[x]], pos[x]), x=fa[belong[x]];
    	return ans;
    }
    
    vector<int> le[maxn], ri[maxn];
    int ans[maxn], que[maxn];
    int main()
    {
    	n=read(); q=read();
    	for(RG int i=2;i<=n;i++) fa[i]=read()+1, add_edge(fa[i], i);
    	dfs(1); dfs(1, 1);
    	RG int l, r, z;
    	for(RG int i=1;i<=q;i++) l=read(), r=read(), z=read(), le[l].push_back(i), ri[r+1].push_back(i), que[i]=z+1;
    	for(RG int i=1;i<=n;i++)
    	{
    		update_chain(i);
    		for(RG auto j : ri[i]) (ans[j]+=query_chain(que[j]))%=mod;
    		for(RG auto j : le[i]) ans[j]=(ans[j]-query_chain(que[j])+mod)%mod;
    	}
    	for(RG int i=1;i<=q;i++) printf("%d
    ", (ans[i]+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    POJ 2661
    POJ 2643
    POJ 2656
    POJ 2612
    POJ 2636
    搭建WordPress个人博客
    【个人笔记】ximo早期发的脱壳教程——手脱UPX壳
    2.1【欢乐向】攻防世界新手逆向刷题被虐哭日常记录
    吾爱破解培训第一课个人笔记
    第五章 计算机组成
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10416255.html
Copyright © 2020-2023  润新知