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\n",((all*all%mod - query(x,y)) % mod + mod)%mod);
        }
    }
    return 0;
}

 

 

posted @ 2017-04-10 20:17  meekyan  阅读(381)  评论(0编辑  收藏  举报