1. 程式人生 > >poj3237tree【樹鏈剖分入門題+線段樹】

poj3237tree【樹鏈剖分入門題+線段樹】

休息了兩天,今天開始做樹鏈剖分,除了模板長以外,還是挺好理解的。就只是線段樹+剖分獨特的函式,然後樹鏈剖分所用的陣列有點多,沒了。其中需要注意的一個點是“鏈”(路徑)不一定是從根節點到葉子節點的,輕兒子這個點它也有重兒子啊啊啊。

再說這個題,單點更新,區間取相反數,區間求最大值。

/***********
poj3237
2015.1.23
2504K	657MS	C++	6396B
***********/
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=101010+5;
const int maxm=maxn+maxn;
struct EDGENODE
{
    int to,w,next;
}edges[maxm];
int head[maxn],edge;
inline void init(){
    edge=0;
    memset(head,-1,sizeof(head));
}
inline void addedge(int u,int v,int w)
{
    edges[edge].w=w,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
    edges[edge].w=w,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++;
}
int que[maxn],son[maxn],idx[maxn],dep[maxn],siz[maxn],belong[maxn],fa[maxn],top[maxn],len[maxn],sump[maxn],seg[maxn],wei[maxn];
int l,r,ans,cnt,n;
bool vis[maxn];
char cmd[22];
void split()
{
    memset(dep,-1,sizeof(dep));
    l=0;
    dep[que[r=1]=1]=0;
    fa[1]=-1;
    wei[1]=0;
    while(l<r)
    {
        int u=que[++l];
        vis[u]=false;
        for(int i=head[u];i!=-1;i=edges[i].next)
        {
            int v=edges[i].to;
            int w=edges[i].w;
            if(dep[v]==-1)
            {
                dep[que[++r]=v]=dep[u]+1;
                fa[v]=u;
                wei[v]=w;
            }
        }
    }
    cnt=0;
    for(int i=n;i>0;i--)
    {
        int u=que[i],p=-1;
        siz[u]=1;
        son[u]=p;
        for(int k=head[u];k!=-1;k=edges[k].next)
        {
            int v=edges[k].to;
            if(vis[v])
            {
                siz[u]+=siz[v];
                if(p==-1||siz[v]>siz[p])
                {
                    son[u]=v;
                    p=v;
                }
            }
        }
        if(p==-1)
        {
            idx[u]=len[++cnt]=1;
            belong[top[cnt]=u]=cnt;
        }
        else
        {
            idx[u]=++len[belong[u]=belong[p]];
            top[belong[u]]=u;
        }
        vis[u]=true;
    }
}
const int INF=0x3f3f3f3f;
struct SegmentTree
{
    int num[maxn];
    struct Tree
    {
        int l,r,max,min;
        bool neg;
    };
    Tree tree[maxn*4];
    void push_down(int root)
    {
        if(tree[root].neg)
        {
            if(tree[root].l!=tree[root].r)
            {
                tree[root<<1].neg^=1;
                tree[root<<1|1].neg^=1;
                swap(tree[root<<1].max,tree[root<<1].min);
                swap(tree[root<<1|1].max,tree[root<<1|1].min);
                tree[root<<1].max*=-1;
                tree[root<<1].min*=-1;
                tree[root<<1|1].max*=-1;
                tree[root<<1|1].min*=-1;
            }
        }
        tree[root].neg=0;
    }
    void push_up(int root)
    {
        tree[root].max=max(tree[root<<1].max,tree[root<<1|1].max);
        tree[root].min=min(tree[root<<1].min,tree[root<<1|1].min);
    }
    void build(int root,int l,int r)
    {
        tree[root].l=l;
        tree[root].r=r;
        tree[root].neg=0;
        if(tree[root].l==tree[root].r)
        {
            tree[root].max=num[l];
            tree[root].min=num[l];
            tree[root].neg=0;
            return;
        }
        int mid=(l+r)/2;
        build(root<<1,l,mid);
        build(root<<1|1,mid+1,r);
        push_up(root);
    }
    void update(int root,int pos,int val)
    {
        if(tree[root].l==tree[root].r)
        {
            tree[root].max=val;
            tree[root].min=val;
            return;
        }
        push_down(root);
        int mid=(tree[root].l+tree[root].r)/2;
        if(pos<=mid)update(root<<1,pos,val);
        else update(root<<1|1,pos,val);
        push_up(root);
    }
    int query(int root,int L,int R)
    {
        if(L<=tree[root].l&&R>=tree[root].r) return tree[root].max;
        push_down(root);
        int mid=(tree[root].l+tree[root].r)/2,ret=-INF;
        if(L<=mid) ret=max(ret,query(root<<1,L,R));
        if(R>mid) ret=max(ret,query(root<<1|1,L,R));
        push_up(root);
        return ret;
    }
    void nega(int root,int L,int R)
    {
        if(L<=tree[root].l&&R>=tree[root].r)
        {
            tree[root].neg^=1;
            swap(tree[root].max,tree[root].min);
            tree[root].max*=-1;
            tree[root].min*=-1;
            return;
        }
        push_down(root);
        int mid=(tree[root].l+tree[root].r)/2;
        if(L<=mid) nega(root<<1,L,R);
        if(R>mid) nega(root<<1|1,L,R);
        push_up(root);
    }
    void debug(int root)
    {
        printf("rt=%d [%d~%d] min=%d max=%d neg=%d\n",root,tree[root].l,tree[root].r,tree[root].min
               ,tree[root].max,(int)tree[root].neg);
        if(tree[root].l==tree[root].r) return;
        debug(root<<1);
        debug(root<<1|1);
    }
}tr;
int find(int va,int vb)
{
    int f1=top[belong[va]],f2=top[belong[vb]],tmp=-INF;
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            swap(f1,f2);
            swap(va,vb);
        }
        tmp=max(tmp,tr.query(1,seg[f1],seg[va]));
        va=fa[f1];
        f1=top[belong[va]];
    }
    if(va==vb) return tmp;
    if(dep[va]>dep[vb]) swap(va,vb);
    return max(tmp,tr.query(1,seg[son[va]],seg[vb]));
}
void gao(int va,int vb)
{
    int f1=top[belong[va]],f2=top[belong[vb]];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            swap(f1,f2);
            swap(va,vb);
        }
        tr.nega(1,seg[f1],seg[va]);
        va=fa[f1];
        f1=top[belong[va]];
    }
    if(va==vb) return;
    if(dep[va]>dep[vb]) swap(va,vb);
    tr.nega(1,seg[son[va]],seg[vb]);
}
int d[maxn][3];
int main()
{
   // freopen("cin.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            d[i][0]=a;
            d[i][1]=b;
            d[i][2]=c;
            addedge(a,b,c);
        }
        split();
        sump[0]=0;
        for(int i=1;i<=cnt;i++) sump[i]=sump[i-1]+len[i];
        for(int i=1;i<=n;i++)
        {
            seg[i]=sump[belong[i]]-idx[i]+1;
            tr.num[seg[i]]=wei[i];
        }
        tr.build(1,1,n);
        while(scanf("%s",cmd))
        {
            if(cmd[0]=='D') break;
            int x,y;
            scanf("%d%d",&x,&y);
            if(cmd[0]=='Q') printf("%d\n",find(x,y));
            if(cmd[0]=='C')
            {
                if(fa[d[x][1]]==d[x][0]) tr.update(1,seg[d[x][1]],y);
                else tr.update(1,seg[d[x][0]],y);
            }
            if(cmd[0]=='N') gao(x,y);
        }
    }
    return 0;
}