• 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
  • 相关阅读:
    EF上下文容器,保存线程唯一性
    zabbix 监控服务器的TCP状态
    C++ 类里面,函数占用存储空间问题
    大道至简第一章读后感(伪代码)
    读大道至简有感
    String 部分源码分析
    LinkedList 源码分析
    ArrayList 源码分析
    定时取数据库的schema,并推送到git服务器
    全面解读python web 程序的9种部署方式
  • 原文地址:https://www.cnblogs.com/ZiningTang/p/4021425.html
Copyright © 2020-2023  润新知