HDU 5405(树链剖分)

来源:互联网 发布:37传奇霸业羽毛数据 编辑:程序博客网 时间:2024/06/06 20:40

(http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106364#problem/D)
题意:一棵树,点权值,两种操作,1.修改u的权值成w,2.查询u,v,求w[i]*w[j],i,j满足i,j的路径与u,v相交。
解法:先求不相交的。
对于每个节点u , 记录两个值
1. sum[u] u子树w之和。
2. sim( sum[v]^2 ) v是u的轻儿子。
每次修改操作时,对1进行区间更新,更改的2的个数最多为lg(n)个,暴力更改。
每次查询操作,区间查询2,单点查询1,即可完成操作。
总结:感觉这种只记录轻儿子还是很套路的。

//#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <queue>//#include <tr1/unordered_set>#include <tr1/unordered_map>#include <bitset>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1#define inf 1e9#define debug(a) cout << #a" = " << (a) << endl;#define debugarry(a, n) for (int i = 0; i < (n); i++) { cout << #a"[" << i << "] = " << (a)[i] << endl; }#define clr(x, y) memset(x, y, sizeof x)#define ll long long#define ull unsigned long long#define FOR(i,a,b) \    for(i=a;a<b?i<=b:i>=b;a<b?i++:i--)const int maxn = 1e5 + 30;const int mod = 1e9+7;struct sad{    int to,next;}G[maxn<<1];int h[maxn],si;void add(int u,int v){//  printf("u %d v %d\n",u,v);    G[si].to=v;    G[si].next=h[u];    h[u]=si++;}int siz[maxn],dep[maxn];int fa[maxn],son[maxn],top[maxn];void dfs1(int u,int f,int d){    fa[u]=f;    dep[u]=d;    siz[u]=1;    son[u]=-1;    for(int i=h[u];~i;i=G[i].next)    {        int v = G[i].to;        if(v^f){            dfs1(v,u,d+1);            siz[u]+=siz[v];            if( son[u] == -1 || siz[son[u]] < siz[v] )                son[u] = v;        }    }}int p[maxn],fp[maxn],pos;void dfs2(int u,int sf){//  printf("u %d sf %d son %d\n",u,sf,son[u]);    //if( u == 0 ) while(1);    top[u] = sf;    p[u] = pos++;    fp[p[u]]=u;    if(son[u]==-1) return ;    dfs2(son[u],sf);    for(int i=h[u];~i;i=G[i].next)    {        int v=G[i].to;//      debug(v);        if(son[u]!=v&&fa[u]!=v)            dfs2(v,v);    }}int rs[maxn];void upp(int x,int p){    while(x<=pos)    {        rs[x] = ((rs[x]+p)%mod+mod)%mod;        x+=x&-x;    }}int get(int x){    int ret = 0;    while(x)    {        ret = (ret+rs[x])%mod;        x-=x&-x;    }    return ret;}int rs2[maxn];void upp2(int x,int p){    while(x<=pos)    {        rs2[x] = ((rs2[x]+p)%mod+mod)%mod;        x+=x&-x;    }}int get2(int x){    int ret = 0;    while(x)    {        ret = (ret+rs2[x])%mod;        x-=x&-x;    }    return ret;}int SUM;void Change(int u,int d){    SUM=(SUM+d)%mod;    while( u != -1 )    {        int f1 = top[u] , f = fa[f1];        int lastsum=get(p[f1]),sum;//      printf("u %d f1 %d d %d\n",u,f1,d);        upp(p[f1],d);        upp(p[u]+1,-d);        if( f != -1 )        {            sum = get(p[f1]);            int t = (ll)sum*sum%mod-(ll)lastsum*lastsum%mod;            t = (t%mod+mod)%mod;            upp2(p[f],t);        }        u = f;    }}int Query(int u,int v){    int f1 = top[u] , f2 = top[v];    int ret = 0;    while(f1^f2)    {        if( dep[f1] < dep[f2] )        {            swap(f1,f2);            swap(u,v);        }        ret = ((ret+get2(p[u])-get2(p[f1]-1))%mod+mod)%mod;        int t = get(p[f1]);        ret = ((ret-(ll)t*t%mod)%mod+mod)%mod;        if( son[u] != -1 ){            int t = get(p[son[u]]);            ret = ((ret+(ll)t*t%mod)%mod+mod)%mod;        }        u = fa[f1];        f1 = top[u];    }    if( dep[u] > dep[v] ) swap(u,v);    ret = ((ret+get2(p[v])-get2(p[u]-1))%mod+mod)%mod;    if( son[v] != -1 ){        int t = get(p[son[v]]);        ret = ((ret+(ll)t*t%mod)%mod+mod)%mod;    }    int t = SUM - get(p[u]);    ret = (ret+(ll)t*t%mod)%mod;    ret = ( (ll)SUM*SUM%mod - ret ) % mod;    return (ret+mod)%mod;}void init(){    clr(h,-1);    si=0;    pos=1;}int w[maxn];int main(){    //freopen("input.txt","r",stdin);    int n,m;    while(~scanf("%d%d",&n,&m))    {        init();        for(int i=1;i<=n;i++)            scanf("%d",&w[i]);        int u,v;        for(int i=0;i<n-1;i++)        {            scanf("%d%d",&u,&v);            add(u,v);            add(v,u);        }        dfs1(1,-1,1);        dfs2(1,1);        clr(rs,0);        clr(rs2,0);        SUM=0;        for(int i=1;i<=n;i++)            Change(i,w[i]);        /*for(int i=1;i<=n;i++)            printf("i %d sum %d\n",i,get(p[i]));*/        int a,b,c;        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&a,&b,&c);            if( a == 1 )            {                Change(b,(c-w[b]+mod)%mod);                w[b] = c;            }else                printf("%d\n",Query(b,c));        }    }    return 0;}
0 0