[树链剖分]

来源:互联网 发布:linux系统编辑文件 编辑:程序博客网 时间:2024/06/05 05:29
/*HDU 3966题意:给n个结点,m条边,p次操作I x y kD x y kx->y的路径上的节点都增加或减少kQ x 查询x结点的权值*/#include <bits/stdc++.h>using namespace std;const int maxn = 50010;int val[maxn],cnt,head[maxn],n;int d[maxn],f[maxn],sz[maxn],son[maxn],top[maxn],id[maxn],tot,rk[maxn];int t[maxn<<2],a[maxn],add[maxn<<2];/*建图*/struct node{    int to,next;} e[maxn<<1];void Init(){    memset(head,-1,sizeof(head));    cnt=0;    memset(son,-1,sizeof(son));    tot=0;}void addEdge(int u,int v){    e[cnt].to=v;    e[cnt].next=head[u];    head[u]=cnt++;}/*树链剖分*/void dfs1(int u,int fa,int depth){    f[u]=fa;    d[u]=depth;    sz[u]=1;    for(int i=head[u]; ~i; i=e[i].next)    {        int v=e[i].to;        if(v!=f[u])        {            dfs1(v,u,depth+1);            sz[u]+=sz[v];            if(son[u]==-1||sz[son[u]]<sz[v])                son[u]=v;        }    }}void dfs2(int u,int tp)/*重新编号*/{    top[u]=tp;    id[u]=++tot;    rk[id[u]]=u;/*记录数组的第i个位置是编号为几的数*/    if(son[u]==-1)        return ;    dfs2(son[u],tp);    for(int i=head[u]; ~i; i=e[i].next)    {        int v=e[i].to;        if(v!=f[u]&&v!=son[u])            dfs2(v,v);    }}/*线段树*/void pushup(int cur){    t[cur]=t[cur<<1]+t[cur<<1|1];}void pushdown(int cur,int l,int r){    int mid=(l+r)>>1;    if(add[cur])    {        add[cur<<1]+=add[cur];        add[cur<<1|1]+=add[cur];        t[cur<<1]+=add[cur]*(mid-l+1);        t[cur<<1|1]+=add[cur]*(r-mid);        add[cur]=0;    }}void build(int cur,int l,int r){    add[cur]=0;    if(l==r)    {        t[cur]=val[rk[l]];        return ;    }    int mid=(l+r)>>1;    build(cur<<1,l,mid);    build(cur<<1|1,mid+1,r);}void Update(int cur,int l,int r,int L,int R,int k){    if(L<=l&&R>=r)    {        add[cur]+=k;        t[cur]+=(r-l+1)*k;        return ;    }    pushdown(cur,l,r);    int mid=(l+r)>>1;    if(L<=mid)        Update(cur<<1,l,mid,L,R,k);    if(R>mid)        Update(cur<<1|1,mid+1,r,L,R,k);    pushup(cur);}int Query(int cur,int l,int r,int index){    int ans;    if(l==r)        return t[cur];    pushdown(cur,l,r);    int mid=(l+r)>>1;    if(index<=mid)        ans=Query(cur<<1,l,mid,index);    else ans=Query(cur<<1|1,mid+1,r,index);    // pushup(cur);    return ans;}void Change(int x,int y,int val){    while(top[x]!=top[y])    {        if(d[top[x]]<d[top[y]])            swap(x,y);        Update(1,1,n,id[top[x]],id[x],val);        x=f[top[x]];    }    if(d[x]>d[y])        swap(x,y);    Update(1,1,n,id[x],id[y],val);}int main(){    int m,p,u,v,y,x,k;    char s[110];    while(~scanf("%d%d%d",&n,&m,&p))    {        Init();        for(int i=1; i<=n; i++)            scanf("%d",&val[i]);        for(int i=1; i<n; i++)        {            scanf("%d%d",&u,&v);            addEdge(u,v);            addEdge(v,u);        }        dfs1(1,0,1);        dfs2(1,1);        build(1,1,n);        while(p--)        {            scanf("%s",s);            if(s[0]=='Q')            {                scanf("%d",&x);                printf("%d\n",Query(1,1,n,id[x]));            }            else            {                scanf("%d%d%d",&x,&y,&k);                if(s[0]=='D')                    k=-k;                Change(x,y,k);            }        }    }    return 0;}/*10 9 51 2 3 4 5 6 7 8 9 101 21 32 83 53 45 75 64 99 10*/

/*FZU 2082 更新边权*/#include <cstdio>#include <cstring>#include <algorithm>typedef long long LL;using namespace std;const int maxn=50010;struct node{    int to,next,w,id;} e[maxn<<1];int n,head[maxn],cnt,f[maxn],d[maxn],son[maxn],sz[maxn],val[maxn],ee[maxn],tot,top[maxn],id[maxn],rk[maxn];void Init(){    memset(head,-1,sizeof(head));    cnt=0;    memset(son,-1,sizeof(son));    tot=0;}void add(int u,int v,int w,int id){    e[cnt].to=v;    e[cnt].w=w;    e[cnt].id=id;    e[cnt].next=head[u];    head[u]=cnt++;}void dfs1(int u,int fa,int depth,int w,int pos){    f[u]=fa;/*记录父亲*/    d[u]=depth;/*记录深度*/    sz[u]=1;/*记录孩子个数,选择重边*/    val[u]=w;/*以u为终点的边的权值为w*/    ee[pos]=u;/*第pos条边的终点为u*/    for(int i=head[u]; ~i; i=e[i].next)    {        int v=e[i].to;        if(v!=fa)        {            dfs1(v,u,depth+1,e[i].w,e[i].id);            sz[u]+=sz[v];            if(son[u]==-1||sz[son[u]]<sz[v])                son[u]=v;        }    }}void dfs2(int u,int tp)/*将同一条链的结点映射到连续的一段区间[]*/{    top[u]=tp;    id[u]=++tot;    rk[id[u]]=u;    if(son[u]==-1)        return ;    dfs2(son[u],tp);    for(int i=head[u]; ~i; i=e[i].next)    {        int v=e[i].to;        if(v!=f[u]&&v!=son[u])            dfs2(v,v);    }}/*线段树 单点更新 区间查询*/LL t[maxn<<2];void pushup(int cur){    t[cur]=t[cur<<1]+t[cur<<1|1];}void build(int cur,int l,int r){    if(l==r)    {        t[cur]=val[rk[l]];        return ;    }    int mid=(l+r)>>1;    build(cur<<1,l,mid);    build(cur<<1|1,mid+1,r);    pushup(cur);}void Update(int cur,int l,int r,int index,int k){    if(l==r)    {        t[cur]=k;        return ;    }    int mid=(l+r)>>1;    if(index<=mid)        Update(cur<<1,l,mid,index,k);    else Update(cur<<1|1,mid+1,r,index,k);    pushup(cur);}LL Query(int cur,int l,int r,int L,int R){    LL ans=0;    if(L<=l&&R>=r)    {        return t[cur];    }    int mid=(l+r)>>1;    if(L<=mid)        ans+=Query(cur<<1,l,mid,L,R);    if(R>mid)        ans+=Query(cur<<1|1,mid+1,r,L,R);    return ans;}void Change(int u,int v){    LL ans=0;    while(top[u]!=top[v])    {        if(d[top[u]]<d[top[v]])            swap(u,v);        ans+=Query(1,1,n,id[top[u]],id[u]);        u=f[top[u]];    }    if(d[u]>d[v])        swap(u,v);    ans+=Query(1,1,n,id[u]+1,id[v]);    printf("%lld\n",ans);}int main(){    int m,u,v,w,op,x,y;    while(~scanf("%d%d",&n,&m))    {        Init();        for(int i=1; i<n; i++)        {            scanf("%d%d%d",&u,&v,&w);            add(u,v,w,i);            add(v,u,w,i);        }        dfs1(1,0,0,0,0);        dfs2(1,1);        build(1,1,n);        while(m--)        {            scanf("%d%d%d",&op,&x,&y);            if(op==0)            {                Update(1,1,n,id[ee[x]],y);            }            else            {                Change(x,y);            }        }    }    return 0;}

//BZOJ 1036 更新点权#include <bits/stdc++.h>#define INF 0x3f3f3f3fusing namespace std;const int maxn=30010;int val[maxn],n;int head[maxn],cnt,d[maxn],f[maxn],sz[maxn],son[maxn],id[maxn],tot,rk[maxn],top[maxn];struct node{    int to,next;} e[maxn<<1];struct pp{    int sum,Max;} t[maxn<<2];void Init(){    memset(head,-1,sizeof(head));    cnt=0;    memset(son,-1,sizeof(son));    tot=0;}void addEdge(int u,int v){    e[cnt].to=v;    e[cnt].next=head[u];    head[u]=cnt++;}void dfs1(int u,int fa,int depth){    d[u]=depth;    f[u]=fa;    sz[u]=1;    for(int i=head[u]; ~i; i=e[i].next)    {        int v=e[i].to;        if(v!=fa)        {            dfs1(v,u,depth+1);            sz[u]+=sz[v];            if(son[u]==-1||sz[son[u]]<sz[v])                son[u]=v;        }    }}void dfs2(int u,int tp){    top[u]=tp;    id[u]=++tot;    rk[id[u]]=u;    if(son[u]==-1)        return ;    dfs2(son[u],tp);    for(int i=head[u]; ~i; i=e[i].next)    {        int v=e[i].to;        if(v!=f[u]&&son[u]!=v)            dfs2(v,v);    }}void pushup(int cur){    t[cur].sum=t[cur<<1].sum+t[cur<<1|1].sum;    t[cur].Max=max(t[cur<<1].Max,t[cur<<1|1].Max);}void build(int cur,int l,int r){    if(l==r)    {        t[cur].Max=t[cur].sum=val[rk[l]];        return ;    }    int mid=(l+r)>>1;    build(cur<<1,l,mid);    build(cur<<1|1,mid+1,r);    pushup(cur);}void Update(int cur,int l,int r,int index,int k){    if(l==r)    {        t[cur].Max=t[cur].sum=k;        return ;    }    int mid=(l+r)>>1;    if(index<=mid)        Update(cur<<1,l,mid,index,k);    else        Update(cur<<1|1,mid+1,r,index,k);    pushup(cur);}int Query(int cur,int l,int r,int L,int R,int flag){    // printf("l = %d r = %d\n",l,r);    int ans;    if(flag)        ans=-INF;/*数据权值有负数 之前设ans=0 WA*/    else ans=0;    if(L<=l&&R>=r)    {        if(flag)            return t[cur].Max;        else return t[cur].sum;    }    int mid=(l+r)>>1;    if(L<=mid)    {        if(flag)            ans=max(ans,Query(cur<<1,l,mid,L,R,flag));        else ans+=Query(cur<<1,l,mid,L,R,flag);    }    if(R>mid)    {        if(flag)            ans=max(ans,Query(cur<<1|1,mid+1,r,L,R,flag));        else ans+=Query(cur<<1|1,mid+1,r,L,R,flag);    }    return ans;//没返回值 debug了好久。。}void Change(int u,int v,int flag){    int ans;    if(flag)        ans=-INF;    else ans=0;    while(top[u]!=top[v])    {        if(d[top[u]]<d[top[v]])            swap(u,v);        if(flag)ans=max(ans,Query(1,1,n,id[top[u]],id[u],flag));        else ans+=Query(1,1,n,id[top[u]],id[u],flag);        u=f[top[u]];    }    if(d[u]>d[v])        swap(u,v);    if(flag)        ans=max(ans,Query(1,1,n,id[u],id[v],flag));    else ans+=Query(1,1,n,id[u],id[v],flag);    printf("%d\n",ans);}int main(){    int u,v,x,y,q;    char s[110];    scanf("%d",&n);    Init();    for(int i=1; i<n; i++)    {        scanf("%d%d",&u,&v);        addEdge(u,v);        addEdge(v,u);    }    for(int i=1; i<=n; i++)        scanf("%d",&val[i]);    dfs1(1,0,0);    dfs2(1,1); //    build(1,1,n);    scanf("%d",&q);    while(q--)    {        scanf("%s",s);        if(s[0]=='C')        {            scanf("%d%d",&x,&y);            Update(1,1,n,id[x],y);        }        else        {            scanf("%d%d",&x,&y);            if(s[1]=='M')                Change(x,y,1);            else                Change(x,y,0);        }    }    return 0;}

0 0