洛谷 P4114 Qtree1

洛谷 P4114 Qtree1

洛谷传送门

题目背景

数据规模和 spoj 上有所不同

题目描述

给定一棵 nn 个节点的树,有两种操作:

  • CHANGE i t 把第 ii 条边的边权变成 tt
  • QUERY a b 输出从 aa 到 bb 的路径上最大的边权。当 a=ba=b 时,输出 00

输入格式

第一行是一个整数 nn,表示节点个数。
第二行到第 nn 行每行输入三个整数 u,v,wu,v,w ,分别表示 uu 与 vv 有一条边,边权是 ww
第 n+1n+1 行开始,一共有不定数量行,每一行先包含一个字符串,分别有以下三种可能:

  • CHANGE 接下来包含两个整数 x, tx,t ,表示一次修改操作。
  • QUERY 接下来包含两个正整数 a, ba,b , 表示一次查询操作。
  • DONE 表示输入结束。

输出格式

对于每个 QUERY 操作,输出一行一个数,表示 a,ba,b 的路径上最大的边权。


题解:

树剖+边转点。

练手模板题。

代码:

#include<bits/stdc++.h>
#define N 100003
#define ls(u) (u<<1)
#define rs(u) (u<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int inf=1e9;
struct edge{
    int u,v,w;
    edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
int wl[N],son[N],size[N],top[N],b[N],id[N];
int a[N<<2],tag[N<<2],depth[N],fa[N],mx[N<<2];
edge e[N];
int n,m,r,cnt;
vector<edge> adj[N];
inline void read(int &x){
    x = 0;
    char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)){
        x = (x<<3)+(x<<1)+c-'0';
        c = getchar();
    }
}
void print(int x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
inline int max(int a,int b){
    return a>b?a:b;
}
inline void push_up(int u){
    a[u] = a[ls(u)]+a[rs(u)];
    mx[u] = max(mx[ls(u)],mx[rs(u)]);
}
void build(int u,int l,int r){
    if(l==r){
        a[u] = mx[u] = wl[l];
        return;
    }
    build(ls(u),l,mid);
    build(rs(u),mid+1,r);
    push_up(u);
}
void update(int u,int l,int r,int q,int k){
    if(l==r){
        a[u] = mx[u] = k;
        return;
    }
    if(q<=mid) update(ls(u),l,mid,q,k);
    else update(rs(u),mid+1,r,q,k);
    push_up(u);
}
int qaq(int nl,int nr,int l,int r,int u){
    int res = -inf;
    if(nl<=l&&r<=nr) return mx[u];
    if(nl<=mid) res = max(res,qaq(nl,nr,l,mid,ls(u)));
    if(nr>mid) res = max(res,qaq(nl,nr,mid+1,r,rs(u)));
    push_up(u);
    return res;
}
inline int qmax(int l,int r){
    return qaq(l,r,1,n,1);
}
void dfs1(int u,int f){
    fa[u] = f;
    depth[u] = depth[f]+1;
    size[u] = 1;
    int v,t = -1,l = adj[u].size();
    for(int i=0;i<l;i++){
        v = adj[u][i].v;
        if(v==f){
            b[u] = adj[u][i].w;
            continue;
        }
        dfs1(v,u);
        size[u] += size[v];
        if(size[v]>t){
            t = size[v];
            son[u] = v;
        }
    }
}
void dfs2(int u,int f)
{
    top[u] = f;
    id[u] = ++cnt;
    wl[cnt] = b[u];
    if(son[u]==0) return;
    dfs2(son[u],f);
    int v,l = adj[u].size();
    for(int i=0;i<l;i++){
        v = adj[u][i].v;
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}
int q_chain(int u,int v)
{
    int res = -inf;
    while(top[u]!=top[v]){
        if(depth[top[u]]<depth[top[v]])
            swap(u,v);
        res = max(res,qmax(id[top[u]],id[u]));
        u = fa[top[u]];
    }
    if(depth[u]>depth[v]) swap(u,v);
    res = max(res,qmax(id[u]+1,id[v]));
    return res;
}
int main()
{
    int u,v,w,q;
    string str;
    read(n);
    for(int i=1;i<n;i++)
	{
        read(u),read(v),read(w);
        adj[u].push_back(edge(u,v,w));
        adj[v].push_back(edge(v,u,w));
        e[i] = edge(u,v,w);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    string op;
    while(1)
	{
        op = "";
        char c = getchar();
        while(c<'A'||c>'Z') 
			c = getchar();
        while(c>='A'&&c<='Z')
		{
            op.push_back(c);
            c = getchar();
        }
        if(op=="DONE") 
			break;
        read(u),read(v);
        if(op=="QUERY")
		{
            if(u==v) 
				putchar('0');
            else 
				print(q_chain(u,v));
            putchar('
');
        }
		else
		{
            if(depth[e[u].u]>depth[e[u].v]) 
				u = e[u].u;
            else 
				u = e[u].v;
            update(1,1,n,id[u],v);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/13851297.html