zoukankan      html  css  js  c++  java
  • SPOJ-375-Qtree-树链剖分(边的剖分)

    【前言】TTvTT先让我呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜一下。。。。。。经历了5发WA,6发RE,3发TLE后,今天终于和这道题做了个了断了。

    题意:一棵树,给出边权值,有两种操作:更改一条边的值;查找a到b路径上的最大边权值。

    【唧唧喳喳】这道题算是树链剖分对边剖分的一道很好的训练题吧,但是数据好像比较变态很容易TLE的样子,嘛啊,其实我也布吉岛。

    【思路】: 对于一棵树,每个节点(除了根节点)都只有一个父亲,那么对于每条边,做儿子的那个节点用来记录边权值。大体就是这样。TvT然后查询的时候,注意和点的剖分的不同的是,查询的时候比较的是链首节点的深度,因为边的剖分不同于点的剖分,比较深度的点存的是与其父节点的连边,所以如果比较最下面的节点,当来到LCA的时候就会往上走多了一个不必走的节点,会出错。

    【总结】:开始用map存节点来对应边,但是TLE了,然后改成用了pre和fun1来对应输入的各边和输入的节点的关系,用tree和fun2对应编号节点和编号。这才过了。

    AC代码(420ms):

    【布吉岛是不是数据变弱了,我用420ms才过,看有些菊苣用了2.6s_(:з」∠)_】

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <climits>
      5 using namespace std;
      6 int const maxn = 10009;
      7 int pre[maxn], n, edge, cnt, fa[maxn], deep[maxn], num[maxn], son[maxn], tree[maxn], fun1[maxn], fun2[maxn];
      8 int to[maxn<<1], next[maxn<<1], head[maxn], top[maxn], seq[maxn<<1], cost[maxn];
      9 void add(int u, int v, int num)
     10 {
     11     to[edge] = v;
     12     next[edge] = head[u];
     13     seq[edge] = num;
     14     head[u] = edge++;
     15 }
     16 void init()
     17 {
     18     scanf("%d", &n);
     19     memset(head, -1, sizeof(head));
     20     memset(son, -1, sizeof(son));
     21     edge = cnt = 0;
     22     for(int i = 1; i < n; i++) {
     23         int a, b; scanf("%d%d%d", &a, &b, &cost[i]);
     24         add(a, b, i); add(b, a, i);
     25     }
     26     fa[1] = deep[1] = tree[1] = 1;
     27 }
     28 void dfs1(int u)
     29 {
     30     num[u] = 1;
     31     for(int e = head[u]; ~e; e = next[e]) {
     32         int too = to[e];
     33         if(fa[u] != too) {
     34             pre[seq[e]] = too;      //把输入的边和较深的节点对应起来
     35             fun1[too] = seq[e];     //存节点对应的边
     36             deep[too] = deep[u]+1;
     37             fa[too] = u;
     38             dfs1(too); num[u] += num[too];
     39             if(son[u] == -1||num[son[u]] < num[too]) son[u] = too;
     40         }
     41     }
     42 }
     43 void dfs2(int u, int lead)
     44 {
     45     top[u] = lead;
     46     if(u != 1) tree[u] = ++cnt, fun2[cnt] = u; //剖分的编号一一对应
     47     if(son[u] == -1) return;
     48     dfs2(son[u], lead);
     49     for(int e = head[u]; ~e; e = next[e]) {
     50         int too = to[e];
     51         if(fa[u] != too && son[u] != too) dfs2(too, too);
     52     }
     53 }
     54 #define lson l, m, rt<<1
     55 #define rson m+1, r, rt<<1|1
     56 int sgt[maxn<<2] = {INT_MIN};
     57 void push_up(int rt)
     58 {
     59     sgt[rt] = max(sgt[rt<<1], sgt[rt<<1|1]);
     60 }
     61 void build(int l, int r, int rt)
     62 {
     63     if(l == r) {
     64         int pos = fun1[fun2[l]];
     65         sgt[rt] = cost[pos]; return;
     66     }
     67     int m = (l+r)>>1;
     68     build(lson); build(rson);
     69     push_up(rt);
     70 }
     71 void change(int l, int r, int rt, int pos, int val)
     72 {
     73     if(l == r) { sgt[rt] = val; return; }
     74     int m = (l+r)>>1;
     75     if(pos <= m) change(lson, pos, val);
     76     if(m < pos) change(rson, pos, val);
     77     push_up(rt);
     78 }
     79 int query(int l, int r, int rt, int L, int R)
     80 {
     81     if(L <= l && r <= R) return sgt[rt];
     82     int m = (l+r)>>1;
     83     int a, b; a = b = INT_MIN;
     84     if(L <= m) a = query(lson, L, R);
     85     if(m < R) b = query(rson, L, R);
     86     return max(a, b);
     87 }
     88 int answer(int a, int b)
     89 {
     90     if(a == b) return 0;
     91     int ans = INT_MIN;
     92     while(top[a] != top[b]) {
     93         if(deep[top[a]] < deep[top[b]]) swap(a, b);
     94         ans = max(ans, query(1, n-1, 1, tree[top[a]], tree[a]));
     95         a = fa[top[a]];
     96     }
     97     if(deep[a] > deep[b]) swap(a, b);
     98     if(a != b) ans = max(ans, query(1, n-1, 1, tree[son[a]], tree[b]));
     99     return ans;
    100 }
    101 void work()
    102 {
    103     init();
    104     dfs1(1); dfs2(1, 1); build(1, n-1, 1);
    105     char s[20];
    106     while(scanf("%s", s) && s[0] != 'D') {
    107         int a, b; scanf("%d%d", &a, &b);
    108         if(s[0] == 'C') {
    109             change(1, n-1, 1, tree[pre[a]], b);
    110         }
    111         else {
    112             printf("%d
    ", answer(a, b));
    113         }
    114     }
    115 }
    116 int main()
    117 {
    118     int t; cin>>t;
    119     while(t--) work();
    120     return 0;
    121 }
    View Code
  • 相关阅读:
    机器学习(深度学习)
    机器学习(六)
    机器学习一-三
    Leetcode 90. 子集 II dfs
    Leetcode 83. 删除排序链表中的重复元素 链表操作
    《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度
    LeetCode 80. 删除有序数组中的重复项 II 双指针
    LeetCode 86 分割链表
    《算法竞赛进阶指南》 第二章 Acwing 138. 兔子与兔子 哈希
    《算法竞赛进阶指南》 第二章 Acwing 137. 雪花雪花雪花 哈希
  • 原文地址:https://www.cnblogs.com/ZiningTang/p/4021425.html
Copyright © 2011-2022 走看看