poj 3237 Tree 树链剖分+lazy标记

来源:互联网 发布:手机淘宝历史版本5.1.1 编辑:程序博客网 时间:2024/05/21 22:44

比较麻烦的树链剖分,其中Neg表示a、b之间所有数取相反数,可以用lazy标记处理,由于代码量略大注意别手残。

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#define maxn 100005#define inf 0x3fffffffusing namespace std;int dep[maxn],top[maxn],id[maxn],son[maxn],size[maxn],num,fa[maxn],tot,head[maxn];struct pppi{    int to;    int next;}pp2[2*maxn];struct ppi{    int f;    int t;    int co;}pp1[maxn];struct pi{    int le;    int ri;    int lazy;    int max;    int min;}pp[4*maxn];void add(int u,int v){    pp2[tot].to=v;    pp2[tot].next=head[u];    head[u]=tot++;    pp2[tot].to=u;    pp2[tot].next=head[v];    head[v]=tot++;}void build(int tot,int l,int r){    pp[tot].le=l;    pp[tot].ri=r;    pp[tot].lazy=0;    pp[tot].max=-inf;    pp[tot].min=inf;    if(l==r) return ;    build(2*tot,l,(l+r)/2);    build(2*tot+1,(l+r)/2+1,r);}int q1(int tot,int l,int r){    if(pp[tot].le>=l&&pp[tot].ri<=r) return pp[tot].lazy;    int s=0;    s+=pp[tot].lazy;    int mid=(pp[tot].le+pp[tot].ri)/2;    if(l<=mid) s+=q1(2*tot,l,r);    if(r>mid) s+=q1(2*tot+1,l,r);    return s;}void push(int tot){    int x1,y1,x2,y2;    if(pp[2*tot].lazy%2==0){ x1=pp[2*tot].max;        x2=pp[2*tot].min;    }    else{        x1=-pp[2*tot].min;        x2=-pp[2*tot].max;    }    if(pp[2*tot+1].lazy%2==0){        y1=pp[2*tot+1].max;        y2=pp[2*tot+1].min;    }    else{        y1=-pp[2*tot+1].min;        y2=-pp[2*tot+1].max;    }    pp[tot].max=max(x1,y1);    pp[tot].min=min(x2,y2);}void merg(int tot,int x,int p){    if(pp[tot].le==pp[tot].ri){        pp[tot].max=p;        pp[tot].min=p;        return ;    }    int mid=(pp[tot].le+pp[tot].ri)/2;    if(x<=mid) merg(2*tot,x,p);    else merg(2*tot+1,x,p);    push(tot);}void merg1(int tot,int l,int r){    if(pp[tot].le>=l&&pp[tot].ri<=r){        pp[tot].lazy++;        return ;    }    int mid=(pp[tot].le+pp[tot].ri)/2;    if(l<=mid) merg1(2*tot,l,r);    if(r>mid) merg1(2*tot+1,l,r);    push(tot);}int query(int tot,int l,int r){    if(pp[tot].le>=l&&pp[tot].ri<=r){        if(q1(1,pp[tot].le,pp[tot].ri)%2==0)        return pp[tot].max;        return -pp[tot].min;    }    int s=-inf,mid=(pp[tot].le+pp[tot].ri)/2;    if(l<=mid) s=max(s,query(2*tot,l,r));    if(r>mid) s=max(s,query(2*tot+1,l,r));    return s;}void dfs1(int u,int pa,int d){    dep[u]=d;    size[u]=1;    son[u]=0;    fa[u]=pa;    int k,v;    k=head[u];    while(k!=-1){        v=pp2[k].to;        if(v!=pa){            dfs1(v,u,d+1);            size[u]+=size[v];            if(size[son[u]]<size[v]) son[u]=v;        }        k=pp2[k].next;    }}void dfs2(int u,int pa,int tp){    top[u]=tp;    id[u]=num++;    if(son[u]) dfs2(son[u],u,tp);    int k,v;    k=head[u];    while(k!=-1){        v=pp2[k].to;        if(v!=pa&&v!=son[u]){            dfs2(v,u,v);        }        k=pp2[k].next;    }}void update(int u,int v){    int to1,to2;    to1=top[u];    to2=top[v];    while(to1!=to2){        if(dep[to1]<dep[to2]||(dep[to1]==dep[to2]&&u<v)){            swap(to1,to2);            swap(u,v);        }        if(!(u==to1&&u==1))        merg1(1,id[to1],id[u]);        u=fa[to1];        to1=top[u];    }    if(u==v) return ;    if(dep[u]>dep[v]) swap(u,v);    merg1(1,id[u]+1,id[v]);}int get(int u,int v){    int to1,to2,s;    s=-inf;    to1=top[u];    to2=top[v];    while(to1!=to2){        if(dep[to1]<dep[to2]){            swap(to1,to2);            swap(u,v);        }        s=max(s,query(1,id[to1],id[u]));        u=fa[to1];        to1=top[u];    }    if(u==v) return s;    if(dep[u]>dep[v]) swap(u,v);    s=max(s,query(1,id[u]+1,id[v]));    return s;}char c[20];int main(){    int t,n,i,p,k;    cin>>t;    while(t--){        scanf("%d",&n);        memset(head,-1,sizeof(head));        tot=0;        num=0;        build(1,1,n-1);        for(i=1;i<n;i++){            scanf("%d%d%d",&pp1[i].f,&pp1[i].t,&pp1[i].co);            add(pp1[i].f,pp1[i].t);        }        dfs1(1,1,1);        dfs2(1,1,1);        for(i=1;i<n;i++){            if(fa[pp1[i].t]==pp1[i].f) merg(1,id[pp1[i].t],pp1[i].co);            else merg(1,id[pp1[i].f],pp1[i].co);        }        while(1){            scanf("%s",c);            if(c[0]=='D') break;            if(c[0]=='Q'){                scanf("%d%d",&p,&k);                if(p==k){                    printf("0\n");                    continue;                }                printf("%d\n",get(p,k));            }            else if(c[0]=='C'){                scanf("%d%d",&p,&k);                if(fa[pp1[p].f]==pp1[p].t){                    if(q1(1,id[pp1[p].f],id[pp1[p].f])%2==0)                    merg(1,id[pp1[p].f],k);                    else  merg(1,id[pp1[p].f],-k);                }                else{                    if(q1(1,id[pp1[p].t],id[pp1[p].t])%2==0)                        merg(1,id[pp1[p].t],k);                    else  merg(1,id[pp1[p].t],-k);                }            }            else if(c[0]=='N'){                scanf("%d%d",&p,&k);                update(p,k);            }        }    }}


0 0
原创粉丝点击