zoukankan      html  css  js  c++  java
  • HDU 5405 Sometimes Naive 树链剖分+bit*****

    Sometimes Naive

    Problem Description
     
    Rhason Cheung had a naive problem, and asked Teacher Mai for help. But Teacher Mai thought this problem was too simple, sometimes naive. So she ask you for help.

    She has a tree with n vertices, numbered from 1 to n. The weight of i-th node is wi.

    You need to support two kinds of operations: modification and query.

    For a modification operation u,w, you need to change the weight of u-th node into w.

    For a query operation u,v, you should output ni=1nj=1f(i,j). If there is a vertex on the path from u to v and the path from i to j in the tree, f(i,j)=wiwj, otherwise f(i,j)=0. The number can be large, so print the number modulo 109+7
     
    Input
    There are multiple test cases.

    For each test case, the first line contains two numbers n,m(1n,m105).

    There are n numbers in the next line, the i-th means wi(0wi109).

    Next n1 lines contain two numbers each, ui and vi, that means that there is an edge between ui and vi.

    The following are m lines. Each line indicates an operation, and the format is "1 u w"(modification) or "2 u v"(query)(0w109)
     
    Output
    For each test case, print the answer for each query operation.
     
    Sample Input
    6 5 1 2 3 4 5 6 1 2 1 3 2 4 2 5 4 6 2 3 5 1 5 6 2 2 3 1 1 7 2 2 4
     
    Sample Output
    341 348 612
     

    题意:

        给你一棵n个节点的树,有点权。

      要求支持两种操作:

        操作1:更改某个节点的权值。

        操作2:给定u,v, 求 Σw[i][j]   i , j 为任意两点且i到j的路径与u到v的路径相交。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e6+10, M = 1e3+20, mod = 1e9+7, inf = 2e9;
    
    LL aa[N],bb[N],in[N],out[N];
    int dep[N],head[N],t=1,sz[N],fa[N],indexS,top[N],pos[N],son[N];
    struct ss{int to,next;}e[N*2];
    int n;
    void add(int u,int v)
    {e[t].to = v;e[t].next = head[u];head[u] = t++;}
    
    void dfs(int u) {
        int k = 0;
        sz[u] = 1;
        if(u!=1)dep[u] = dep[fa[u]] + 1;
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(to == fa[u]) continue;
            fa[to] = u;
            dfs(to);
            sz[u] += sz[to];
            if(sz[to] > sz[k]) k = to;
        }
        if(k) son[u] = k;
    }
    void dfs(int u,int chain) {
        int k = 0;
        pos[u] = ++indexS;
        in[u] = indexS;
        top[u] = chain;
        if(son[u] > 0)
            dfs(son[u],chain);
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(dep[to] > dep[u] && son[u] != to)
                dfs(to,to);
        }
        out[u] = indexS;
    }
    
    void update(int x,LL val,LL *sum) {
        for(int i = x; i < N; i += i&(-i)) {
            sum[i] += val;
            sum[i] %= mod;
        }
    }
    LL ask(int x,LL *sum) {
        LL res = 0;
        for(int i = x; i; i-=i&(-i)) res += sum[i],res %= mod;
        return res;
    }
    
    LL allsum,C_tree[N],C_sqtree[N],a[N];
    void update(int x,LL val) {
        int u = top[x];
        while(fa[u] > 0) {
            LL all = ask(out[u],C_tree) - ask(in[u]-1,C_tree);
            LL newall = (val - a[x])*(val - a[x])%mod + 1LL*2*all*(val-a[x])%mod;
            update(in[fa[u]],newall%mod,C_sqtree);
            u = top[fa[u]];
        }
        update(in[x],val-a[x],C_tree);
        a[x] = val;
    }
    LL query(int x,int y) {
        LL res = 0,hav = 0;
        while(top[x] != top[y]) {
            if(dep[top[x]] < dep[top[y]]) swap(x,y);
            res += ask(in[x],C_sqtree) - ask(in[top[x]]-1,C_sqtree);
            res %= mod;
            if(son[x]>0) {
                LL all = ask(out[son[x]],C_tree) - ask(in[son[x]]-1,C_tree);
                res += all*all;
                res %= mod;
            }
            if(hav>0) {
                LL all = ask(out[hav],C_tree) - ask(in[hav]-1,C_tree);
                res -= all * all;
                res %= mod;
            }
            hav = top[x];
            x = fa[hav];
        }
        if(dep[x] < dep[y]) swap(x,y);
        res += ask(in[x],C_sqtree) - ask(in[y]-1,C_sqtree);
        res %= mod;
        if(fa[y] > 0) {
            LL all = ((ask(out[1],C_tree) - ask(out[y],C_tree) + ask(in[y]-1,C_tree))%mod+mod)%mod;
            res += (all*all)%mod;
            res %= mod;
        }
        if(son[x]>0) {
            LL all = ask(out[son[x]],C_tree) - ask(in[son[x]]-1,C_tree);
            res += all*all;
            res %= mod;
        }
        if(hav>0) {
            LL all = ask(out[hav],C_tree) - ask(in[hav]-1,C_tree);
            res -= all * all;
            res %= mod;
        }
        return res;
    }
    int Q;
    void init() {
        memset(head,0,sizeof(head));
        t = 1;
        indexS = 0;
        allsum = 0;
        memset(son,-1,sizeof(son));
        son[0] = 0;
        memset(C_tree,0,sizeof(C_tree));
        memset(C_sqtree,0,sizeof(C_sqtree));
    }
    int main() {
        while(scanf("%d%d",&n,&Q)!=EOF) {
            init();
            for(int i = 1; i <= n; ++i)
                scanf("%I64d",&a[i]);
            allsum = allsum*allsum%mod;
            for(int i = 1; i < n; ++i) {
                int x,y;
                scanf("%d%d",&x,&y);
                add(x,y),add(y,x);
            }
            fa[1] = -1;
            dfs(1);
            dfs(1,1);
            for(int i = 1; i <= n; ++i) {
                LL uu = a[i];
                a[i] = 0;
                update(i,uu);
            }
            while(Q--) {
                int op,x;
                LL y;
                LL all = ask(out[1],C_tree);
                scanf("%d%d%I64d",&op,&x,&y);
                if(op == 1) {
                    update(x,y);
                }
                else
                    printf("%I64d
    ",((all*all%mod - query(x,y)) % mod + mod)%mod);
            }
        }
        return 0;
    }

     

  • 相关阅读:
    使用Twitter异常检测框架遇到的坑
    Python从入门到精通
    Windows中几个内存相当的指标
    Windows应用程序进程级别统一监控实践
    基于时序数据的微内核预警引擎架构设计
    Flink1.4.0连接Kafka0.10.2时遇到的问题
    wait和sleep的区别
    JVM几种垃圾回收器介绍
    二叉树的非递归遍历
    段页式内存管理
  • 原文地址:https://www.cnblogs.com/zxhl/p/6690719.html
Copyright © 2011-2022 走看看