HDU 4010 Query on The Trees (动态树)

题意:给定一个棵树,有四种操作,

1 连接两棵树,

2 把两棵树分开,

3 给 a 到 b 路径上的每个点加一个权值 w,

4 询问 a 到 b 的最大值。

析:最大值,很明显是要维护的,然后用就是一个裸板动态树。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(x,n)  for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 300000 + 10;
const int mod = 1000;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
  return r > 0 && r <= n && c > 0 && c <= m;
}

int ch[maxn][2], pre[maxn], key[maxn];
int addv[maxn], rev[maxn], maxv[maxn];
bool is_rt[maxn];

void update_add(int rt, int d){
  if(!rt)  return ;
  key[rt] += d;
  addv[rt] += d;
  maxv[rt] += d;
}

void update_rev(int rt){
  if(!rt)  return ;
  swap(ch[rt][0], ch[rt][1]);
  rev[rt] ^= 1;
}

void push_down(int rt){
  if(addv[rt]){
    update_add(ch[rt][0], addv[rt]);
    update_add(ch[rt][1], addv[rt]);
    addv[rt] = 0;
  }
  if(rev[rt]){
    update_rev(ch[rt][0]);
    update_rev(ch[rt][1]);
    rev[rt] = 0;
  }
}

void push_up(int rt){
  maxv[rt] = max(maxv[ch[rt][0]], max(maxv[ch[rt][1]], key[rt]));
}

void rotate(int x){
  int y = pre[x], kind = ch[y][1] == x;
  ch[y][kind] = ch[x][!kind];
  pre[ch[y][kind]] = y;
  pre[x] = pre[y];
  pre[y] = x;
  ch[x][!kind] = y;
  if(is_rt[y])  is_rt[y] = 0, is_rt[x] = 1;
  else  ch[pre[x]][ch[pre[x]][1]==y] = x;
  pu(y);
}

void PP(int rt){
  if(!is_rt[rt])  PP(pre[rt]);
  pd(rt);
}

void splay(int rt){
  PP(rt);
  while(!is_rt[rt]){
    int f = pre[rt], ff = pre[f];
    if(is_rt[f])  rotate(rt);
    else if((ch[ff][1]==f) == (ch[f][1]==rt))  rotate(f), rotate(rt);
    else rotate(rt), rotate(rt);
  }
  pu(rt);
}

int access(int x){
  int y = 0;
  for( ; x; x = pre[y=x]){
    splay(x);
    is_rt[ch[x][1]] = 1, is_rt[ch[x][1]=y] = 0;
    pu(x);
  }
  return y;
}

bool judge(int u, int v){
  while(pre[u])  u = pre[u];
  while(pre[v])  v = pre[v];
  return u == v;
}

void mroot(int rt){
  access(rt);
  splay(rt);
  update_rev(rt);
}

void lca(int &u, int &v){
  access(v), v = 0;
  while(u){
    splay(u);
    if(!pre[u])  return ;
    is_rt[ch[u][1]] = 1;
    is_rt[ch[u][1]=v] = 0;
    pu(u);
    u = pre[v = u];
  }
}

void link(int u, int v){
  if(judge(u, v)){
    puts("-1");
    return ;
  }
  mroot(u);
  pre[u] = v;
}

void cut(int u, int v){-
  if(u == v || !judge(u, v)){
    puts("-1");
    return ;
  }
  mroot(u);
  splay(v);
  pre[ch[v][0]] = pre[v];
  pre[v] = 0;
  is_rt[ch[v][0]] = 1;
  ch[v][0] = 0;
  pu(v);
}

void add(int u, int v, int w){
  if(!judge(u, v)){
    puts("-1");
    return ;
  }
  lca(u, v);
  update_add(ch[u][1], w);
  update_add(v, w);
  key[u] += w;
  pu(u);
}

void query(int u, int v){
  if(!judge(u, v)){
    puts("-1");
    return ;
  }
  lca(u, v);
  printf("%d
", max(maxv[v], max(maxv[ch[u][1]], key[u])));
}

struct Edge{
  int to, next;
};
Edge edge[maxn<<1];
int head[maxn], cnt;

void addEdge(int u, int v){
  edge[cnt].to = v;
  edge[cnt].next = head[u];
  head[u] = cnt++;
}

void dfs(int u){
  for(int i = head[u]; ~i; i = edge[i].next){
    int v = edge[i].to;
    if(pre[v])  continue;
    pre[v] = u;
    dfs(v);
  }
}

int main(){
  while(scanf("%d", &n) == 1){
    cnt = 0;
    for(int i = 0; i <= n; ++i){
      is_rt[i] = 1;  head[i] = -1;
      ch[i][0] = ch[i][1] = 0;
      pre[i] = rev[i] = 0;
      addv[i] = 0;
    }
    for(int i = 1; i < n; ++i){
      int u, v;
      scanf("%d %d", &u, &v);
      addEdge(u, v);
      addEdge(v, u);
    }
    maxv[0] = -INF;
    for(int i = 1; i <= n; ++i){
      scanf("%d", key+i);
      maxv[i] = key[i];
    }
    pre[1] = -1;
    dfs(1);
    pre[1] = 0;
    scanf("%d", &m);
    int op, x, y;
    while(m--){
      scanf("%d", &op);
      if(op == 3){
        int w;
        scanf("%d %d %d", &w, &x, &y);
        add(x, y, w);
      }
      else{
        scanf("%d %d", &x, &y);
        if(op == 1)  link(x, y);
        else if(op == 2)  cut(x, y);
        else query(x, y);
      }
    }
    printf("
");
  }
  return 0;
}

  

原文地址:https://www.cnblogs.com/dwtfukgv/p/7507589.html