POJ-3237:Tree(树链剖分)

人走茶凉 提交于 2019-11-30 10:04:17

Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 10785   Accepted: 2800

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 ab and c, describing an edge connecting nodes a and bwith 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

思路:树链剖分。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
const int MAX=2e5;
struct edg{int x,y,z;}edg[MAX];
vector<int>e[MAX];
struct lenka
{
    int l,r;
    int ma;
}A[MAX<<2];
int d[MAX],son[MAX],fa[MAX],siz[MAX],top[MAX],val[MAX],num[MAX],all;
void build(int k,int l,int r)
{
    A[k].l=l,A[k].r=r;
    if(l==r){A[k].ma=val[l];return;}
    build(2*k,l,(l+r)/2);
    build(2*k+1,(l+r)/2+1,r);
    A[k].ma=max(A[2*k].ma,A[2*k+1].ma);
}
void negat(int k,int x,int y)
{
    if(A[k].l==A[k].r){A[k].ma*=-1;return;}
    if(y<=A[2*k].r)negat(2*k,x,y);
    else if(x>=A[2*k+1].l)negat(2*k+1,x,y);
    else
    {
        negat(2*k,x,A[2*k].r);
        negat(2*k+1,A[2*k+1].l,y);
    }
    A[k].ma=max(A[2*k].ma,A[2*k+1].ma);
}
void change(int k,int x,int y)
{
    if(x==A[k].l&&x==A[k].r){A[k].ma=y;return;}
    if(x<=A[2*k].r)change(2*k,x,y);
    else change(2*k+1,x,y);
    A[k].ma=max(A[2*k].ma,A[2*k+1].ma);
}

int ask(int k,int x,int y)
{
    if(x==A[k].l&&y==A[k].r)return A[k].ma;
    if(y<=A[2*k].r)return ask(2*k,x,y);
    else if(x>=A[2*k+1].l)return ask(2*k+1,x,y);
    return max(ask(2*k,x,A[2*k].r),ask(2*k+1,A[2*k+1].l,y));
}
void dfs1(int k,int f,int dep)
{
    d[k]=dep;
    siz[k]=1;
    son[k]=0;
    fa[k]=f;
    for(int i=0;i<e[k].size();i++)
    {
        int nex=e[k][i];
        if(nex==f)continue;
        dfs1(nex,k,dep+1);
        siz[k]+=siz[nex];
        if(siz[son[k]]<siz[nex])son[k]=nex;
    }
}
void dfs2(int k,int tp)
{
    top[k]=tp;
    num[k]=++all;
    if(son[k])dfs2(son[k],tp);
    for(int i=0;i<e[k].size();i++)
    {
        if(e[k][i]==fa[k]||e[k][i]==son[k])continue;
        dfs2(e[k][i],e[k][i]);
    }
}
int QWQ(int x,int y)
{
    int tpx=top[x],tpy=top[y],ans=-(1<<30);//数据范围不知道,一开始设的为0,一直WA
    while(tpx!=tpy)
    {
        if(d[tpx]<d[tpy])
        {
            swap(tpx,tpy);
            swap(x,y);
        }
        ans=max(ans,ask(1,num[tpx],num[x]));
        x=fa[tpx];
        tpx=top[x];
    }
    if(x==y)return ans;
    if(d[x]>d[y])swap(x,y);
    return max(ans,ask(1,num[son[x]],num[y]));
}
void QAQ(int x,int y)
{
    int tpx=top[x],tpy=top[y];
    while(tpx!=tpy)
    {
        if(d[tpx]<d[tpy])
        {
            swap(tpx,tpy);
            swap(x,y);
        }
        negat(1,num[tpx],num[x]);
        x=fa[tpx];
        tpx=top[x];
    }
    if(x==y)return;
    if(d[x]>d[y])swap(x,y);
    negat(1,num[son[x]],num[y]);
}
int main()
{
    int T,n;cin>>T;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)e[i].clear();
        memset(siz,0,sizeof siz);
        memset(d,0,sizeof d);
        memset(son,0,sizeof son);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&edg[i].x,&edg[i].y,&edg[i].z);
            e[edg[i].x].push_back(edg[i].y);
            e[edg[i].y].push_back(edg[i].x);
        }
        all=0;
        dfs1(1,0,1);
        dfs2(1,1);
        for(int i=1;i<n;i++)
        {
            if(d[edg[i].x]<d[edg[i].y])swap(edg[i].x,edg[i].y);
            val[num[edg[i].x]]=edg[i].z;
        }
        build(1,1,all);
        char op[20];
        while(scanf("%s",op)!=EOF&&strcmp(op,"DONE")!=0)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(strcmp(op,"QUERY")==0)printf("%d\n",QWQ(x,y));
            else if(strcmp(op,"CHANGE")==0)change(1,num[edg[x].x],y);
            else QAQ(x,y);
        }
    }
    return 0;
}





易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!