poj3237 Tree

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b
Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input
1
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output
1
3

分析:
树链剖分

样例输入2
1
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
NEGATE 1 2
QUERY 1 2
DONE

样例输出2
1
3
-3

tip

题目中的
NEGATE这个操作是取反
(zz,看了半天题目)

这里写代码片
#include
#include
#include

using namespace std;

const int INF=0x33333333;
const int N=10010;
struct node{
    int x,y,v,nxt;
};
node way[N<<1];
int n,cnt=0,val[N],pre[N],deep[N],st[N],tot=0,son[N],top[N],num[N],shu[N],wz[N],size[N];
struct nd{
    int x,y,mx,la,mn;
};
nd t[N<<2];

void add(int u,int w,int z)
{
    tot++;
    way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
    tot++;
    way[tot].x=w;way[tot].y=u;way[tot].v=z;way[tot].nxt=st[w];st[w]=tot;
}

void dfs1(int now,int fa,int dep)
{
    pre[now]=fa;
    deep[now]=dep;
    size[now]=1;
    son[now]=0;
    int mx=0;
    for (int i=st[now];i;i=way[i].nxt)
        if (way[i].y!=fa)
        {
            dfs1(way[i].y,now,dep+1);
            val[way[i].y]=way[i].v; wz[(i+1)/2]=way[i].y;
            size[now]+=size[way[i].y];
            if (size[way[i].y]>mx)
            {
                mx=size[way[i].y];
                son[now]=way[i].y;
            }
        }
}

void dfs2(int now,int fa)
{
    if (son[fa]!=now) top[now]=now;
    else top[now]=top[fa];
    num[now]=++cnt; shu[num[now]]=now;
    if (son[now])
    {
        dfs2(son[now],now);
        for (int i=st[now];i;i=way[i].nxt)
            if (way[i].y!=fa&&way[i].y!=son[now])
               dfs2(way[i].y,now);
    }
}

void update(int bh)
{
    t[bh].mx=max(t[bh<<1].mx,t[bh<<1|1].mx);
    t[bh].mn=min(t[bh<<1].mn,t[bh<<1|1].mn);
}

void build(int bh,int l,int r)
{
    t[bh].x=l;t[bh].y=r;
    t[bh].mx=-INF;
    t[bh].mn=INF;
    t[bh].la=0;
    if (l==r)
    {
        if (l!=1){
            t[bh].mx=t[bh].mn=val[shu[l]];
        }
        return;
    }
    int mid=(l+r)>>1;
    build(bh<<1,l,mid);
    build(bh<<1|1,mid+1,r);
    update(bh);
}

void rotate(int bh)
{
    t[bh].mx*=-1;
    t[bh].mn*=-1;
    swap(t[bh].mn,t[bh].mx);
}

void push(int bh)
{
    if (t[bh].la&&t[bh].x!=t[bh].y)
    {
        t[bh<<1].la^=1;
        rotate(bh<<1);
        t[bh<<1|1].la^=1;
        rotate(bh<<1|1);
        t[bh].la^=1;
    }
}

void change(int bh,int wz,int z)
{
    push(bh);
    if (t[bh].x==t[bh].y)
    {
        t[bh].mx=t[bh].mn=z;
        return;
    }
    int mid=(t[bh].x+t[bh].y)>>1;
    if (wz<=mid) change(bh<<1,wz,z);
    else change(bh<<1|1,wz,z);
    update(bh);
}

int ask(int bh,int l,int r)
{
    push(bh);   //
    if (t[bh].x>=l&&t[bh].y<=r)
    {
        return t[bh].mx;
    }
    int mid=(t[bh].x+t[bh].y)>>1;
    int ans=-INF;
    if (l<=mid) ans=max(ans,ask(bh<<1,l,r));
    if (r>mid) ans=max(ans,ask(bh<<1|1,l,r));
    return ans;
}

int askmax(int u,int w)
{
    int f1=top[u];
    int f2=top[w];
    int ans=-INF;
    while (f1!=f2)
    {
        if (deep[f1]1,num[f1],num[u]));
        u=pre[f1];
        f1=top[u];
    }
    if (u==w) return ans;
    if (num[u]>num[w]) swap(u,w);
    ans=max(ans,ask(1,num[son[u]],num[w]));
    return ans==-INF? 0:ans;    ///
}

void gg(int bh,int l,int r)
{
    push(bh);
    if (t[bh].x>=l&&t[bh].y<=r)
    {
        t[bh].la=1;
        rotate(bh);   //取反 
        return;
    }
    int mid=(t[bh].x+t[bh].y)>>1;
    if (l<=mid) gg(bh<<1,l,r);
    if (r>mid) gg(bh<<1|1,l,r);
    update(bh);
}

void fan(int u,int w)
{
    int f1=top[u];
    int f2=top[w];
    while (f1!=f2)
    {
        if (deep[f1]1,num[f1],num[u]);
        u=pre[f1];
        f1=top[u];
    }
    if (u==w) return;
    if (num[u]>num[w]) swap(u,w);
    gg(1,num[son[u]],num[w]);
    return;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        memset(st,0,sizeof(st));   //laji的初始化 
        memset(t,0,sizeof(t));
        memset(deep,0,sizeof(deep));
        memset(shu,0,sizeof(shu));
        memset(num,0,sizeof(num));
        tot=0; cnt=0;

        scanf("%d",&n);
        for (int i=1;iint u,w,z;
            scanf("%d%d%d",&u,&w,&z);
            add(u,w,z);
        }
        char opt[10];
        dfs1(1,0,1);
        dfs2(1,0);
        build(1,1,n);
        scanf("%s",&opt);
        while (opt[0]!='D')
        {
            int u,w;
            scanf("%d%d",&u,&w);
            if (opt[0]=='C')
               change(1,num[wz[u]],w);
            else if (opt[0]=='N')
               fan(u,w);
            else if (opt[0]=='Q')
               printf("%d\n",askmax(u,w));
            scanf("%s",&opt);
        }
    }
    return 0;
}

你可能感兴趣的:(树链剖分,树链剖分)