• Bzoj3626 [LNOI2014]LCA


    先把问题简化,怎样求一个点x和y的lca的deep和
    显然直接求LCA,但是这样的话,要求多个就不好叠加
    于是可以用奇技淫巧:先把x到根的所有点打上标记,那么询问y到根的标记的个数即为答案,这样就可以叠加
    所以对于询问,拆成[1,l-1], [1, r],排序后依次加点覆盖标记即可

    可以用树链剖分+线段树,或者Orz yyb大佬一样写LCT

    代码

    表示不想写LCT

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(1e5 + 10), __(1e6 + 10), INF(2e9), MOD(201314);
    
    IL ll Read(){
        char c = '%'; ll x = 0, z = 1;
        for(; c > '9' || c < '0'; c = getchar()) if(c == '-') z = -1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
        return x * z;
    }
    
    int n, q, cnt, fst[_], to[_], nxt[_], fa[_], son[_], size[_], top[_], deep[_], dfn[_];
    int sum[__], tag[__], ans[_], z[_];
    struct Data{
        int f, id, type;
        IL bool operator <(RG Data B) const{  return f < B.f;  }
    } qry[_];
    
    IL void Add(RG int u, RG int v){  to[cnt] = v; nxt[cnt] = fst[u]; fst[u] = cnt++;  }
    
    IL void Dfs1(RG int u){
        size[u] = 1;
        for(RG int e = fst[u]; e != -1; e = nxt[e]){
            if(size[to[e]]) continue;
            deep[to[e]] = deep[u] + 1; fa[to[e]] = u;
            Dfs1(to[e]);
            size[u] += size[to[e]];
            if(size[to[e]] > size[son[u]]) son[u] = to[e];
        }
    }
    
    IL void Dfs2(RG int u, RG int Top){
        top[u] = Top; dfn[u] = ++cnt;
        if(son[u]) Dfs2(son[u], Top);
        for(RG int e = fst[u]; e != -1; e = nxt[e])
            if(!dfn[to[e]]) Dfs2(to[e], to[e]);
    }
    
    IL void Update(RG int x){  sum[x] = (sum[x << 1] + sum[x << 1 | 1]) % MOD;  }
    
    IL void Pushdown(RG int x, RG int l, RG int r){
        if(!tag[x]) return;
        RG int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1;
        (sum[ls] += (mid - l + 1) * tag[x]) %= MOD;
        (sum[rs] += (r - mid) * tag[x]) %= MOD;
        tag[ls] += tag[x]; tag[rs] += tag[x]; tag[x] = 0;
    }
    
    IL void Modify(RG int x, RG int l, RG int r, RG int L, RG int R){
        if(L <= l && R >= r){
            (sum[x] += r - l + 1) %= MOD; tag[x]++;
            return;
        }
        Pushdown(x, l, r);
        RG int mid = (l + r) >> 1;
        if(L <= mid) Modify(x << 1, l, mid, L, R);
        if(R > mid) Modify(x << 1 | 1, mid + 1, r, L, R);
        Update(x);
    }
    
    IL int Query(RG int x, RG int l, RG int r, RG int L, RG int R){
        if(L <= l && R >= r) return sum[x];
        Pushdown(x, l, r);
        RG int mid = (l + r) >> 1, Ans = 0;
        if(L <= mid) Ans = Query(x << 1, l, mid, L, R);
        if(R > mid) Ans += Query(x << 1 | 1, mid + 1, r, L, R);
        Update(x);
        return Ans;
    }
    
    IL void Cover(RG int x, RG int y){
        while(top[x] != top[y]){
            if(deep[top[x]] < deep[top[y]]) swap(x, y);
            Modify(1, 1, n, dfn[top[x]], dfn[x]);
            x = fa[top[x]];
        }
        if(deep[x] < deep[y]) swap(x, y);
        Modify(1, 1, n, dfn[y], dfn[x]);
    }
    
    IL int Calc(RG int x, RG int y){
        RG int Ans = 0;
        while(top[x] != top[y]){
            if(deep[top[x]] < deep[top[y]]) swap(x, y);
            Ans += Query(1, 1, n, dfn[top[x]], dfn[x]);
            x = fa[top[x]];
        }
        if(deep[x] < deep[y]) swap(x, y);
        Ans += Query(1, 1, n, dfn[y], dfn[x]);
        return Ans;
    }
    
    int main(RG int argc, RG char *argv[]){
        n = Read(); q = Read(); Fill(fst, -1);
        for(RG int i = 2, a; i <= n; ++i) a = Read() + 1, Add(a, i), Add(i, a);
        Dfs1(1); cnt = 0; Dfs2(1, 1); cnt = 0;
        for(RG int i = 1; i <= q; ++i){
            qry[++cnt].f = Read(); qry[cnt].id = i; qry[cnt].type = -1;
            qry[++cnt].f = Read() + 1; qry[cnt].id = i; qry[cnt].type = 1;
            z[i] = Read() + 1;
        }
        sort(qry + 1, qry + cnt + 1);
        for(RG int i = 1, j = 0; i <= cnt; ++i){
            while(j < qry[i].f) ++j, Cover(1, j);
            ans[qry[i].id] += qry[i].type * Calc(1, z[qry[i].id]);
        }
        for(RG int i = 1; i <= q; i++) printf("%d
    ", (ans[i] % MOD + MOD) % MOD);
        return 0;
    }
    
  • 相关阅读:
    深入探索迭代器(续)
    深入探索迭代器
    C++ 容器的综合应用的一个简单实例——文本查询程序
    multimap 和 multiset 类型
    set 类型
    map 类型
    关联容器
    Ajax请求成功, 但进不去success方法
    springboot指定配置文件启动项目
    新测可用IntelliJ IDEA 2020.1 for mac
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8206336.html
Copyright © 2020-2023  润新知