spoj375 quert on a tree(树剖板子)

大致题意:
给定一棵树,有两种操作:
1:Q x y 表示询问树上x~y的路径上的最大权值
2:C x y 表示修改第x条边的权值为y
3:Done 结束这组输入
输入格式
输入数据第一行一个正整数T,代表一共有T组数据。

接下来每组数据,第一行一个正整数N,意义如题面所示。

接下来N-1行,每行三个整数x、y、w描述一条枝干,分别代表这条枝干连接的两个结点的编号和这条枝干的初始长度。

接下来不知道多少行,每行一个字符串s和两个整数x、y,若s为”QUERY”,请输出结点x到y之间所有枝干最粗的粗细;若s为”CHANGE”,请将编号为x的枝干粗细改为y;若s为”DONE”,则本组数据结束。

输出格式
输出数据不知道多少行,对于每个询问操作,输出其答案。
input
1
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
output
1
3
数据规模与约定
T≤20,N≤10000,w≤1000000。


树剖板子题。
修改操作没有看清楚题目直接对编号为x的节点的父边修改了QAQ,调了好久

#include<bits/stdc++.h>
using namespace std;
#define ls root * 2
#define rs root * 2 + 1
int n , Q , linkk[101000] , t;
int size[101000] , son[101000] , fa[101000] , dep[101000];
int top[101000] , w[101000] , totw , tmp[101000];
int tr[401000]; 
struct node{ 
    int n , y , v;
}e[201000];
int read()
{
    int sum = 0;char c = getchar();bool flag = true;
    while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
    while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
    if(flag)  return sum;
     else return -sum;
}  
void insert(int x,int y,int z)
{
    e[++t].y = y;e[t].n = linkk[x];e[t].v = z;linkk[x] = t;
    e[++t].y = x;e[t].n = linkk[y];e[t].v = z;linkk[y] = t;
    return;
}
void dfs1(int x,int f)
{
    dep[x] = dep[f] + 1;
    fa[x] = f;
    int Max = 0;
    for(int i = linkk[x];i;i = e[i].n)
        if(e[i].y != f)
        {
            int y = e[i].y;
            dfs1(y , x);
            size[x] += size[y];
            if(size[y] > Max) son[x] = y , Max = size[y]; 
        }
    size[x]++;
}
void dfs2(int x)
{
    if(x != 1)w[x] = ++totw;
    top[x] = x == son[fa[x]] ? top[fa[x]] : x;
    if(son[x])dfs2(son[x]);
    for(int i = linkk[x];i;i = e[i].n)
        if(e[i].y != fa[x] && e[i].y != son[x])
            dfs2(e[i].y);       
    return;
}
int Lca(int x,int y)
{
    for(;top[x] != top[y];)
        dep[top[x]] > dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
    return dep[x] < dep[y] ? x : y;
}
void build(int root,int l,int r)
{

    if(l == r)
    {
        tr[root] = tmp[l];
        return;
    }
    int mid = (l + r)>>1;
    build(ls , l , mid);
    build(rs , mid + 1 , r);
    tr[root] = max(tr[ls] , tr[rs]);
    return;
} 
int query(int root,int l,int r,int x,int y)
{
    if( r < x || l > y ) return 0;
    if( x <= l && y >= r ) return tr[root];
    int mid = (l + r)>>1;
    return max( query(ls , l , mid , x , y) , query(rs , mid + 1 , r , x , y) ); 
} 
int ask(int a,int b)
{
    int ans = 0;
    if(a == b) return ans;
    int ta = top[a] , tb = top[b];
    while(ta != tb)
    {
        if(dep[ta] < dep[tb]) 
            swap(ta , tb) , swap(a , b);
        ans = max(ans , query(1 , 1 , n - 1, w[ta] , w[a]));
        a = fa[ta];
        ta = top[a]; 
    }
    if(a == b) return ans;
    if(dep[a] > dep[b]) swap(a , b) , swap(ta , tb);
    ans = max(ans , query(1 , 1 , n - 1,w[son[a]] , w[b]));
    return ans;
}
void change(int root,int l,int r,int pl,int v)
{
    if(l == r)
    {
        tr[root] = v;
        return;
    }
    int mid = (l + r)>>1;
    if(pl <= mid) change(ls , l , mid , pl , v);
        else change(rs , mid + 1 , r , pl , v);
    tr[root] = max(tr[ls] , tr[rs]);
    return;
}
void init()
{
    memset(linkk , 0 , sizeof(linkk));
    memset(tr , 0 , sizeof(tr));
    memset(son , 0 , sizeof(son));
    memset(size , 0 , sizeof(size)); 
    t = 0;totw = 0;
    n = read();
    for(int i = 1;i < n;++i)
    {
        int x = read() , y = read() , z = read();
        insert(x , y , z);
    }
    dfs1(1 , 0);
    dfs2(1);
    for(int x = 1;x <= n;++x)
        for(int i = linkk[x];i;i = e[i].n)
            if(e[i].y != fa[x])
                tmp[ w[e[i].y] ] = e[i].v;
    build(1,1,n - 1);
    while(1)
    {
        char c = getchar();
        while(c != 'Q' && c != 'C' && c != 'D') c = getchar();
        if(c == 'D') break;
        int x = read() , y = read();
        if(c == 'Q') printf("%d\n",ask(x , y));
        else 
        {
            int a = dep[e[2 * x - 1].y] , b = dep[e[2 * x].y];
            x = a < b ? e[2 * x].y : e[2 * x - 1].y; 
            change(1 , 1 , n - 1 , w[x] , y);
        }
    }
    return;
} 
int main()
{
    int T = read();
    while(T--)  init();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1035719430/article/details/81148928