HDU 3237 Tree(树链剖分)(线段树区间取反,最大值)

Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 9123   Accepted: 2411

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
【分析】题意很好理解,唯一的难点就是将某一区间内的数变成相反数,需要用到懒惰标记。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N=2e5+50;
const int M=N*N+10;
int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N]; //top 最近的重链父节点
int num,s,m,n,q;
int sum[N*2],tre[2*N];
int maxn[N],minn[N],lazy[N];
vector<int> v[N];
struct tree {
    int x,y,val;
    void read() {
        scanf("%d%d%d",&x,&y,&val);
    }
} e[N];
void dfs1(int u, int f, int d) {
    dep[u] = d;
    siz[u] = 1;
    son[u] = 0;
    fa[u] = f;
    for (int i = 0; i < v[u].size(); i++) {
        int ff = v[u][i];
        if (ff == f) continue;
        dfs1(ff, u, d + 1);
        siz[u] += siz[ff];
        if (siz[son[u]] < siz[ff])
            son[u] = ff;
    }
}
void dfs2(int u, int tp) {
    top[u] = tp;
    id[u] = ++num;
    if (son[u]) dfs2(son[u], tp);
    for (int i = 0; i < v[u].size(); i++) {
        int ff = v[u][i];
        if (ff == fa[u] || ff == son[u]) continue;
        dfs2(ff, ff);
    }
}
void ChangeVal(int rt) {
    int tmp=maxn[rt];
    maxn[rt]=-minn[rt];
    minn[rt]=-tmp;
}
void Push_up(int rt) {
    maxn[rt]=max(maxn[2*rt],maxn[2*rt+1]);
    minn[rt]=min(minn[2*rt],minn[2*rt+1]);
}
void Push_down(int rt) {
    if(lazy[rt]) {
        lazy[rt]^=1;
        lazy[2*rt]^=1;
        ChangeVal(rt*2);
        lazy[2*rt+1]^=1;
        ChangeVal(2*rt+1);
    }
}
void change(int t,int l,int r,int x,int v){
    if(l==r) maxn[t]=minn[t]=v;
    else{
        Push_down(t);
        int mid=(l+r)>>1;
        if(x<=mid) change(t*2,l,mid,x,v);
        else change(t*2+1,mid+1,r,x,v);
        Push_up(t);
    }
}
void  Build(int l,int r,int rt) {
    if(l==r) {
        maxn[rt]=minn[rt]=val[l];
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    Push_up(rt);
    //printf("rt=%d sum[rt]=%d\n",rt,sum[rt]);
}

void Update(int L,int R,int l,int r,int rt) {
    if(l>=L&&r<=R) {
        lazy[rt]^=1;
        ChangeVal(rt);
        return;
    }
    Push_down(rt);
    int m=(r+l)>>1;
    if(L<=m)Update(L,R,lson);
    if(R>m) Update(L,R,rson);
    Push_up(rt);
}

int Query(int L,int R,int l,int r,int rt) {
    if(L<=l&&r<=R)return maxn[rt];
    Push_down(rt);
    int m=(l+r)>>1;
    if(R<=m)return Query(L,R,lson);
    else if(L>m)return Query(L,R,rson);
    else return max(Query(L,m,lson),Query(m+1,R,rson));
}

void solve(int u, int v) {
    int tp1 = top[u], tp2 = top[v];
    int ans = 0;
    while (tp1 != tp2) {
        if (dep[tp1] < dep[tp2]) {
            swap(tp1, tp2);
            swap(u, v);
        }
        Update(id[tp1],id[u],1,n,1);
        u = fa[tp1];
        tp1 = top[u];
    }
    if (u == v) return;
    if (dep[u] > dep[v]) swap(u, v);
    Update(id[son[u]],id[v],1,n,1);
    return;
}
int Yougth(int u,int v) {
    int tp1 = top[u], tp2 = top[v];
    int ans=-10000000;
    while (tp1 != tp2) {
        if (dep[tp1] < dep[tp2]) {
            swap(tp1, tp2);
            swap(u, v);
        }
        ans = max(Query(id[tp1], id[u],1,n,1),ans);
        u = fa[tp1];
        tp1 = top[u];
    }
    if (u == v) return ans;
    if (dep[u] > dep[v]) swap(u, v);
    ans = max(Query(id[son[u]], id[v],1,n,1),ans);
    return ans;
}
void Clear(int n) {
    for(int i=1; i<=n; i++)
        v[i].clear();
    met(son,0);met(maxn,0);met(minn,0);
    met(lazy,0);
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        Clear(n);
        int u,vv,w;
        for(int i=1; i<n; i++) {
            e[i].read();
            v[e[i].x].push_back(e[i].y);
            v[e[i].y].push_back(e[i].x);
        }
        num = 0;
        dfs1(1,0,1);
        dfs2(1,1);
        for (int i = 1; i < n; i++) {
            if (dep[e[i].x] < dep[e[i].y]) swap(e[i].x, e[i].y);
            val[id[e[i].x]] = e[i].val;
        }
        Build(1,num,1);
        char str[20];
        while(~scanf("%s",str)) {
            if(str[0]=='D')break;
            if(str[0]=='C') {
                scanf("%d%d",&u,&vv);
                if(dep[e[u].x]<dep[e[u].y])swap(e[u].x,e[u].y);
                change(1,1,n,id[e[u].x],vv);
            } else if(str[0]=='N'){
                scanf("%d%d",&u,&vv);
                solve(u,vv);
            }else {
                scanf("%d%d",&u,&vv);
                if(u==vv)puts("0");
                else printf("%d\n",Yougth(u,vv));
            }
        }

    }

    return 0;
}

 

posted @ 2017-01-30 01:19  贱人方  阅读(454)  评论(0编辑  收藏  举报