POJ - 3237 树链剖分

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 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=10005;
const int inf=0x3f3f3f3f;
struct point
{
    int lazy,ll,rr,maxw,minw;
} tree[maxn*4];//线段树
int LL,RR,val,ind;
int pre[maxn],siz[maxn],dep[maxn],son[maxn];//第一次dfs处理的内容
int top[maxn],in[maxn],befcod[maxn];//第二次dfs处理的内容
int befval[maxn],dfstime;
vector vec[maxn];//存边
struct edge1
{
    friend bool operator < (edge1 a1 ,edge1 a2); //由于要放入map容器,建立点与边的映射关系,所以得定义一个排序规则
    edge1(){a=b=0;}
    edge1(int x,int y){a=x,b=y;}
    int a,b;
};
bool operator < (edge1 a1 ,edge1 a2){//得对edge1的两个变量都排序,否则储存时会出问题,这与map的内部原理有关
    if(a1.a==a2.a)
        return a1.b map1;
void dfs1(int u,int bef,int deep)
{
    pre[u]=bef;
    dep[u]=deep;
    siz[u]=1;//初始化u自身为一个节点
    for(int i=0; isiz[son[u]])
            son[u]=vec[u][i];//重儿子是siz值最大的儿子节点
    }
}
void dfs2(int u,int bef,int t)
{
    in[u]=++dfstime;
    befcod[dfstime]=u;
    top[u]=t;
    if(!son[u])//当为叶子节点时
        return;
    dfs2(son[u],u,t);//先处理重儿子,使得重链dfs序连续
    for(int i=0; i=tree[k].rr)
    {
        int bet=tree[k].maxw;
        tree[k].maxw=-tree[k].minw;
        tree[k].minw=-bet;
        tree[k].lazy^=1;
        return;
    }
    if(tree[k].lazy)
        pushdown(k);
    int bet=(tree[k].ll+tree[k].rr)/2;
    if(LL<=bet)
        NEGATE(k*2);
    if(RR>bet)
        NEGATE(k*2+1);
    pushup(k);
}
void CHANGE(int k,int point)//单点更新
{
    if(tree[k].ll==tree[k].rr){
        tree[k].minw=tree[k].maxw=val;
        return;
    }
    if(tree[k].lazy) pushdown(k);
    int bet=(tree[k].ll+tree[k].rr)/2;
    if(point<=bet) CHANGE(k*2,point);
    else CHANGE(k*2+1,point);
    pushup(k);
}
int QUERY(int k)//区间询查
{
    if(LL<=tree[k].ll&&RR>=tree[k].rr)
        return tree[k].maxw;
    if(tree[k].lazy)
        pushdown(k);
    int bet=(tree[k].ll+tree[k].rr)/2,askval=-inf;
    if(LL<=bet)
        askval=max(askval,QUERY(k*2));
    if(RR>bet)
        askval=max(askval,QUERY(k*2+1));
    return askval;
}
int ask(int x,int y)
{
    int ans=-inf,fx=top[x],fy=top[y];
    while(fx!=fy)//当x y不在同一条重链时
    {
        if(dep[fx]>=dep[fy])//先走较深的节点
        {
            LL=in[fx],RR=in[x];
            ans=max(ans,QUERY(1));
            x=pre[fx],fx=top[x];
        }
        else
        {
            LL=in[fy],RR=in[y];
            ans=max(ans,QUERY(1));
            y=pre[fy],fy=top[y];
        }
    }//循环,直到x y在同一重链上
    if(in[x]+1<=in[y]){
        LL=in[x]+1,RR=in[y];
        ans=max(ans,QUERY(1));
    }
    else if(in[y]+1<=in[x]){
        LL=in[y]+1,RR=in[x];
        ans=max(ans,QUERY(1));
    }
    return ans;
}
void change(int x,int y)//同理
{
    int fx=top[x],fy=top[y];
    while(fx!=fy)
    {
        if(dep[fx]>=dep[fy])
        {
            LL=in[fx],RR=in[x];
            NEGATE(1);
            x=pre[fx],fx=top[x];
        }
        else
        {
            LL=in[fy],RR=in[y];
            NEGATE(1);
            y=pre[fy],fy=top[y];
        }
    }
    if(in[x]+1<=in[y]){
        LL=in[x]+1,RR=in[y];
        NEGATE(1);
    }
    else if(in[y]+1<=in[x]){
        LL=in[y]+1,RR=in[x];
        NEGATE(1);
    }
}
char ss[10];
//int checkind;
//void check(int k) //输出叶子节点的值,用于检测树是否出现问题
//{
//    if(tree[k].ll==tree[k].rr){
//        printf("i==%d  maxw=%d minw=%d\n",++checkind,tree[k].maxw,tree[k].minw);
//        return;
//    }
//    if(tree[k].lazy) pushdown(k);
//    check(k*2);
//    check(k*2+1);
//}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out2.txt","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--){
        ind=dfstime=0;
        memset(son,0,sizeof(son));
        map1.clear();
        int n;
        scanf("%d",&n);
        for(int i=1;i

 

你可能感兴趣的:(POJ - 3237 树链剖分)