zoukankan      html  css  js  c++  java
  • 【LOJ】#2558. 「LNOI2014」LCA

    题解

    当年LN还是有专门的省选题的,但是还不如没有

    看到这道题,我就想到了一个清晰易懂,简单好写,代码优美的树链剖分线段树套主席树的(O(qlog^{3}n))做法,且就5组数据出题人肯定是不会出题树剖卡不到上限……

    但是我太菜了,我并不想实现这个算法……然后看了看一个神奇的(O(n log^{2} n))离线做法

    我们注意到,实际上所求就是z到根节点路径上,每个点子树里的点下标在[l,r]的有多少个的和
    首先区间都是可以拆成前缀和加减的,然后我们离线,往树链剖分加入每个节点,然后对于询问拆成两个前缀和的询问,排序依次查询回答即可

    吐槽
    1.模数没有任何意义,只是为了秀,还让人注意不到
    2.我数组开小了,gg

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    //#define ivorysi
    #define pb push_back
    #define MAXN 50005
    #define space putchar(' ')
    #define enter putchar('
    ')
    using namespace std;
    typedef long long int64;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) putchar('-'),x = -x;
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    const int MOD = 201314;
    struct node {
        int to,next;
    }E[MAXN * 2];
    struct qry {
        int id,on,pos,z;
        friend bool operator < (const qry &a,const qry &b) {
    	return a.pos < b.pos;
        }
    }Qry[MAXN * 2];
    int head[MAXN],sumE,N,Q,siz[MAXN],top[MAXN],son[MAXN],fa[MAXN],dfn[MAXN],tot;
    int ans[MAXN],tr[MAXN * 4],lz[MAXN * 4];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void dfs1(int u) {
        siz[u]++;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa[u]) {
    	    fa[v] = u;
    	    dfs1(v);
    	    siz[u] += siz[v];
    	    if(siz[v] > siz[son[u]]) son[u] = v;
    	}
        }
    }
    void dfs2(int u) {
        dfn[u] = ++tot;
        if(!top[u]) top[u] = u;
        if(son[u]) {top[son[u]] = top[u];dfs2(son[u]);}
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa[u] && v != son[u]) dfs2(v);
        }
    }
    void addlazy(int u,int L,int R,int v) {
        tr[u] = (tr[u] + (R - L + 1) * v) % MOD;lz[u] = lz[u] + v;
    }
    void push_down(int u,int L,int R) {
        int mid = (L + R) >> 1;
        if(lz[u]) {
    	addlazy(u << 1,L,mid,lz[u]);
    	addlazy(u << 1 | 1,mid + 1,R,lz[u]);
    	lz[u] = 0;
        }
    }
    void Add(int u,int L,int R,int l,int r,int v) {
        if(L == l && R == r) {addlazy(u,L,R,v);return;}
        int mid = (L + R) >> 1;
        push_down(u,L,R);
        if(r <= mid) Add(u << 1,L,mid,l,r,v);
        else if(l > mid) Add(u << 1 | 1,mid + 1,R,l,r,v);
        else Add(u << 1,L,mid,l,mid,v),Add(u << 1 | 1,mid + 1,R,mid + 1,r,v);
        tr[u] = (tr[u << 1] + tr[u << 1 | 1]) % MOD;
    }
    int Query(int u,int L,int R,int l,int r) {
        if(L == l && R == r) return tr[u];
        push_down(u,L,R);
        int mid = (L + R) >> 1;
        if(r <= mid) return Query(u << 1,L,mid,l,r);
        else if(l > mid) return Query(u << 1 | 1,mid + 1,R,l,r);
        else return Query(u << 1,L,mid,l,mid) + Query(u << 1 | 1,mid + 1,R,mid + 1,r);
    }
    void Init() {
        read(N);read(Q);
        for(int i = 2 ; i <= N ; ++i) {
    	int f;read(f);++f;
    	add(i,f);add(f,i);
        }
        int l,r,z;
        for(int i = 1 ; i <= Q ; ++i) {
    	read(l);read(r);read(z);++l;++r;++z;
    	Qry[i * 2 - 1].id = i;Qry[i * 2 - 1].on = -1;Qry[i * 2 - 1].pos = l - 1;Qry[i * 2 - 1].z = z;
    	Qry[i * 2].id = i;Qry[i * 2].on = 1;Qry[i * 2].pos = r;Qry[i * 2].z = z;
        }
        sort(Qry + 1,Qry + 2 * Q + 1);
        dfs1(1);
        dfs2(1);
    }
    void Insert(int x) {
        while(top[x] != 1) {
    	Add(1,1,N,dfn[top[x]],dfn[x],1);
    	x = fa[top[x]];
        }
        Add(1,1,N,dfn[top[x]],dfn[x],1);
    }
    int Query(int x) {
        int res = 0;
        while(top[x] != 1) {
    	res += Query(1,1,N,dfn[top[x]],dfn[x]) % MOD;
    	x = fa[top[x]];
        }
        res += Query(1,1,N,dfn[top[x]],dfn[x]);
        return res % MOD;
    }
    void Solve() {
        int p = 1;
        while(Qry[p].pos < 1) ++p;
        for(int i = 1 ; i <= N ; ++i) {
    	Insert(i);
    	while(Qry[p].pos == i) {
    	    ans[Qry[p].id] += Qry[p].on * Query(Qry[p].z) % MOD;
    	    ++p;
    	}
        }
        for(int i = 1 ; i <= Q ; ++i) {
    	ans[i] = (ans[i] % MOD + MOD) % MOD;
    	out(ans[i]);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    
  • 相关阅读:
    蚂蚁的难题(一) http://acm.nyist.net/JudgeOnline/status.php?pid=744
    快速查找素数 http://acm.nyist.net/JudgeOnline/problem.php?pid=187
    我排第几个 http://acm.nyist.net/JudgeOnline/problem.php?pid=139
    求余数 http://acm.nyist.net/JudgeOnline/problem.php?pid=205
    九的余数 http://acm.nyist.net/JudgeOnline/problem.php?pid=105
    次方求模 http://acm.nyist.net/JudgeOnline/problem.php?pid=102
    汉诺塔(一)http://acm.nyist.net/JudgeOnline/problem.php?pid=88
    换博客了,欢迎访问
    linux下使用kpartx挂载虚拟文件系统
    编译linux内核时出错
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9075723.html
Copyright © 2011-2022 走看看