[BZOJ1036][JZOJ2256]【ZJOI2008】树的统计(树链剖分模板)

来源:互联网 发布:js date format 函数 编辑:程序博客网 时间:2024/06/06 03:25

Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
  I. CHANGE u t : 把结点u的权值改为t
  II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
  III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身

Solution

链剖裸题。。。。。。

Code

#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;struct note{    int l,r,sum,mx,ls,rs;   };struct nt1{    int x,y;    };note tree[100001];int top[30001],deep[30001],size[30001],pt[30001],dfn[30001],ft[30001],son[30001],a[30001],lazy[100001];nt1 a1[60001];int a2[30001][2];int n,m,dfm;bool cmp(nt1 x,nt1 y){    return x.x<y.x;}void give(int f,int k){    tree[k].mx=lazy[f];    tree[k].sum=(tree[k].r-tree[k].l+1)*lazy[f];}void newptl(int f,int l,int r){    if (tree[f].ls==0)    {        tree[f].ls=++m;        tree[m].l=l;        tree[m].r=r;    }}void newptr(int f,int l,int r){    if (tree[f].rs==0)    {        tree[f].rs=++m;        tree[m].l=l;        tree[m].r=r;    }}void find(int now,int l,int r,int &sm,int &ma){    if (tree[now].l==l&&tree[now].r==r)    {        sm=tree[now].sum;        ma=tree[now].mx;        return;    }    int ls=tree[now].ls,rs=tree[now].rs;    if (lazy[now]!=1802201963)    {        if (ls!=0) give(now,ls);        if (rs!=0) give(now,rs);        lazy[now]=1802201963;    }    int mid=(tree[now].l+tree[now].r)/2;    if (r<=mid) find(ls,l,r,sm,ma);    else if(l>mid) find(rs,l,r,sm,ma);    else    {        int s1,m1;        find(ls,l,mid,sm,ma);        find(rs,mid+1,r,s1,m1);        sm+=s1;        ma=max(ma,m1);    }    tree[now].sum=tree[tree[now].ls].sum+tree[tree[now].rs].sum;    tree[now].mx=max(tree[tree[now].ls].mx,tree[tree[now].rs].mx);}void ask(int u,int v,int &sm,int &ma,bool uh,bool vh){    int s1=0,m1=-1802201963,s2=0,m2=-1802201963;    if (u==v)     {        if (uh==0&&vh==0)        {            find(1,dfn[u],dfn[v],s1,m1);            sm=s1;            ma=m1;            return;        }        sm=0;        ma=-1802201963;        return;    }    int f1=top[u],f2=top[v];    if (f1==f2)    {        if (deep[u]>deep[v]) swap(u,v);        find(1,dfn[u],dfn[v],sm,ma);        return;    }    else    {        if (deep[f1]<deep[f2])         {            swap(u,v);            swap(f1,f2);            swap(uh,vh);        }        find(1,dfn[f1],dfn[u],s1,m1);        if (ft[f1]==f1) ask(ft[f1],v,s2,m2,1,vh);        else ask(ft[f1],v,s2,m2,0,vh);        sm=s1+s2;        ma=max(m1,m2);    }}void change(int now,int l,int r,int dt){    if (tree[now].l==l&&tree[now].r==r)    {        tree[now].mx=dt;        tree[now].sum=(r-l+1)*dt;        lazy[now]=dt;        return;    }    int ls=tree[now].ls,rs=tree[now].rs;    int mid=(tree[now].l+tree[now].r)/2;    if (lazy[now]!=1802201963)    {        if (ls!=0) give(now,ls);        if (rs!=0) give(now,rs);        lazy[now]=1802201963;    }    if (r<=mid)    {        newptl(now,tree[now].l,mid);        change(tree[now].ls,l,r,dt);    }    else if(l>mid)    {        newptr(now,mid+1,tree[now].r);        change(tree[now].rs,l,r,dt);    }    else    {        newptl(now,tree[now].l,mid);        newptr(now,mid+1,tree[now].r);        change(tree[now].ls,l,mid,dt);        change(tree[now].rs,mid+1,r,dt);    }    tree[now].sum=tree[tree[now].ls].sum+tree[tree[now].rs].sum;    tree[now].mx=max(tree[tree[now].ls].mx,tree[tree[now].rs].mx);}void dfs1(int k,int f,int dep){    int i,sz=0,sn=0,wsn=0;    fo(i,a2[k][0],a2[k][1])    {        int p=a1[i].y;        if (p!=f)        {            ft[p]=k;            dfs1(p,k,dep+1);            sz+=size[p];            if (size[p]>sn)             {                sn=size[p];                wsn=p;            }         }    }    size[k]=sz+1;    son[k]=wsn;    deep[k]=dep;}void dfs2(int k,int f){    dfn[k]=++dfm;    change(1,dfn[k],dfn[k],a[k]);    int i;    if (son[k]!=0)    {        top[son[k]]=top[k];        dfs2(son[k],k);    }    fo(i,a2[k][0],a2[k][1])    {        int p=a1[i].y;        if (p!=f&&p!=son[k])        {            top[p]=p;            dfs2(p,k);        }    }}int main(){    cin>>n;    int i,j,s1,m1;    fo(i,1,n-1)     {        scanf("%d%d",&a1[2*i-1].x,&a1[2*i-1].y);        a1[2*i].x=a1[2*i-1].y;        a1[2*i].y=a1[2*i-1].x;    }    sort(a1+1,a1+2*n-1,cmp);    fo(i,1,2*n-2)    {        if (a1[i].x!=a1[i-1].x)        {            a2[a1[i].x][0]=i;            a2[a1[i-1].x][1]=i-1;        }    }    a2[a1[2*n-2].x][1]=2*n-2;    fo(i,1,n) scanf("%d",&a[i]);    memset(lazy,107,sizeof(lazy));    dfs1(1,0,1);    dfm=0;    top[1]=1;    m=1;    tree[1].l=1;    tree[1].r=n;    dfs2(1,0);    ft[1]=1;    scanf("\n");    int cz;    scanf("%d",&cz);    scanf("\n");    int ct=0;    fo(i,1,cz)    {        char c,c1;        scanf("%c%c",&c,&c1);        if (c=='C')        {            int x,t;            scanf("ANGE %d%d\n",&x,&t);            change(1,dfn[x],dfn[x],t);        }        else        {            int su,ma,u,v;            if (c1=='M') scanf("AX %d%d\n",&u,&v);            else scanf("UM %d%d\n",&u,&v);            if (u==v) find(1,dfn[u],dfn[v],su,ma);                          else ask(u,v,su,ma,0,0);            if (c1=='M') printf("%d\n",ma);            else printf("%d\n",su);        }    }}
0 0
原创粉丝点击