zoukankan      html  css  js  c++  java
  • BZOJ 5293: [Bjoi2018]求和 树链剖分+鬼畜代码

    5293: [Bjoi2018]求和

    >原题链接<

    Description

    master 对树上的求和非常感兴趣。他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k
     次方和,而且每次的k 可能是不同的。此处节点深度的定义是这个节点到根的路径上的边数。他把这个问题交给
    了pupil,但pupil 并不会这么复杂的操作,你能帮他解决吗?

    Input

    第一行包含一个正整数n ,表示树的节点数。
    之后n-1 行每行两个空格隔开的正整数i,j ,表示树上的一条连接点i 和点j 的边。
    之后一行一个正整数m ,表示询问的数量。
    之后每行三个空格隔开的正整数i,j,k ,表示询问从点i 到点j 的路径上所有节点深度的k 次方和。
    由于这个结果可能非常大,输出其对998244353 取模的结果。
    树的节点从1 开始标号,其中1 号节点为树的根。

    Output

    对于每组数据输出一行一个正整数表示取模后的结果。
    1≤n,m≤300000,1≤k≤50

    Sample Input

    5
    1 2
    1 3
    2 4
    2 5
    2
    1 4 5
    5 4 45

    Sample Output

    33
    503245989

    思路:

      因为k很小, 所以我们对50个次方都预处理一下答案, 用dis数组表示, 最后的a->b的答案就是dis(a)+dis(b)-dis(fa[lca(a, b)]);;

    本篇代码采用鬼畜数组表达方式/指针邻接表存边。码风清奇,邀您一看!

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cctype>
    #define ll long long
    #define GG puts("Fuck!")
    #define max(a, b) (a>b?a:b)
    using namespace std;
    const int N = 310000, K = 60;
    const int mod = 998244353;
    inline char Nc() {
        static char Buf[100000], *p1, *p2;
        return p1==p2&&(p2=(p1=Buf)+fread(Buf, 1, 100000, stdin), p1==p2)?EOF:*p1++;
    }
    int Rd() {
        int x = 0;char c = Nc();
        while(!isdigit(c)) c=Nc();
        while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=Nc();
        return x;
    }
    int dep[N], top[N], fa[N], son[N], siz[N], maxinum, dis[N][K];
    int pwr[N][K];
    struct Edge {
        int to;
        Edge *next;
    }*h[N], e[N<<1];
    int _, n;
    void Add_Edge(int u, int v) {
        Edge *tmp = &(++_)[e];
        tmp -> to = v;
        tmp -> next = u[h];
        h[u] = tmp;
    
        tmp = &(++_)[e];
        tmp -> to = u;
        tmp -> next = h[v];
        v[h] = tmp;
    }
    void Dfs1(int p) {
        dep[p] = p[fa][dep] + 1;
        for(int i=1;i<=50;i++)i[p[dis]] = (i[p[fa][dis]] + pwr[dep[p]-1][i])%mod;
        p[siz] = 1;
        maxinum = max(maxinum, p[dep]);
        for(Edge *i = p[h];i;i=i->next) {
            int to = i->to;
            if(to!=p[fa]) {
                to[fa] = p;
                Dfs1(to);
                p[siz] += to[siz];
                if(to[siz] > p[son][siz]) p[son] = to;    
            }
        }
    }
    void Dfs2(int p, int t) {
        p[top] = t;
        if(p[son]) Dfs2(son[p], t);
        for(Edge *i = p[h];i;i=i->next) {
            int to = i -> to;
            if(to!=p[fa]&&to!=p[son]) {
                Dfs2(to, to);
            }
        }
    }
    void Test() {
        /*for(int i=1;i<=5;i++) printf("%d ", i[dep]);
        puts("Fuck");*/
        GG;
        for(Edge *i = 2[h];i;i=i->next) {
            int to = i -> to;
            printf("%d
    ", to);
        }
        GG;
    }
    void Init() {
        n=Rd();
        for(int i=2;i<=n;i++) {
            int u=Rd(), v=Rd();
            Add_Edge(u, v);
        }
        for(int i=1;i<=n;i++) {
            0[i[pwr]] = 1;
            for(int j=1;j<=50;j++) {
                j[i[pwr]] = ((ll)(j-1)[i[pwr]] * i)%mod;
            }
        }
        /*for(int i=1;i<=n;i++) {
            for(int j=1;j<=50;j++) {
                printf("%d %d %d
    ", i, j, pwr[i][j]);
            }
        }*/
        Dfs1(1);
        Dfs2(1, 1);
        //Test();
    }
    void solve(int x, int y, int k) {
        int ret = 0;
        ret += (k[x[dis]]+ k[y[dis]]) %mod;
        while(x[top] != y[top]) {
            if(x[top][dep] < y[top][dep]) swap(x, y);
                x = x[top][fa];
            //printf("**%d**
    ", x);
        }
        int ans = (x[dep] < y[dep]) ? x : y;
        //printf("--%d--
    ", ans);
        ret -= k[ans[dis]];
        ret -= k[ans[fa][dis]];
        ((ret%=mod)+=mod)%=mod;
        printf("%d
    ", ret);
    }
    int main() {
        Init();
        int q = Rd();
        while(q--) {
            int x=Rd(), y=Rd(), k=Rd();
            solve(x, y, k);
        }
    }
    打开新世界!
  • 相关阅读:
    暑假D16 T3 密道(数位DP? 打表找规律)
    暑假D16 T2 无聊 (深搜)
    暑假D14 T3 cruise(SDOI2015 寻宝游戏)(虚树+set)
    Django url
    http协议
    host文件以及host的作用
    用socket写一个简单的服务器
    python中*args **kwargs
    javascript 判断对像是否相等
    html input标签详解
  • 原文地址:https://www.cnblogs.com/Tobichi/p/9243265.html
Copyright © 2011-2022 走看看