zoukankan      html  css  js  c++  java
  • BZOJ 3757: 苹果树

    3757: 苹果树

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 1726  Solved: 550
    [Submit][Status][Discuss]

    Description

        神犇家门口种了一棵苹果树。苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条。由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色。我们用一个到n之间的正整数来表示一种颜色。树上一共有n个苹果。每个苹果都被编了号码,号码为一个1到n之间的正整数。我们用0代表树根。只会有一个苹果直接根。

    有许许多多的人来神犇家里膜拜神犇。可神犇可不是随便就能膜拜的。前来膜拜神犇的人需要正确回答一个问题,才能进屋膜拜神犇。这个问题就是,从树上编号为u的苹果出发,由树枝走到编号为v的苹果,路径上经过的苹果一共有多少种不同的颜色(包括苹果u和苹果v的颜色)?不过神犇注意到,有些来膜拜的人患有色盲症。具体地说,一个人可能会认为颜色a就是颜色b,那么他们在数苹果的颜色时,如果既出现了颜色a的苹果,又出现了颜色b的苹果,这个人只会算入颜色b,而不会把颜色a算进来。

    神犇是一个好人,他不会强人所难,也就会接受由于色盲症导致的答案错误(当然答案在色盲环境下也必须是正确的)。不过这样神犇也就要更改他原先数颜色的程序了。虽然这对于神犇来说是小菜一碟,但是他想考验一下你。你能替神犇完成这项任务吗?

     

    Input

    输入第一行为两个整数n和m,分别代表树上苹果的个数和前来膜拜的人数。
     
    接下来的一行包含n个数,第i个数代表编号为i的苹果的颜色Coli。
     
    接下来有n行,每行包含两个数x和y,代表有一根树枝连接了苹果x和y(或者根和一个苹果)。
     
    接下来有m行,每行包含四个整数u、v、a和b,代表这个人要数苹果u到苹果v的颜色种数,同时这个人认为颜色a就是颜色b。如果a=b=0,则代表这个人没有患色盲症。

    Output

    输出一共m行,每行仅包含一个整数,代表这个人应该数出的颜色种数。

    Sample Input

    5 3
    1 1 3 3 2
    0 1
    1 2
    1 3
    2 4
    3 5
    1 4 0 0
    1 4 1 3
    1 4 1 2

    Sample Output

    2
    1
    2

    HINT

    0<=x,y,a,b<=N

    N<=50000

    1<=U,V,Coli<=N

    M<=100000

    此题存在版权,故不再支持提交,保留在此只供大家参考题面! 望见谅!

    Source

     
    [Submit][Status][Discuss]

    树上莫队的模板题。

    仿照序列莫队的方式对树进行适当的sqrt(n)分块,然后按照区间左端点的所在块分组;每组内按照右端点的DFS序排序。易知两个组内询问转移答案时,左端点至多移动O(sqrt(n)),而右端点全局是O(n)的,复杂度O(Nsqrt(N))。至于维护哪些点以及如何转移,网上有很详细的解释。

      1 #include <bits/stdc++.h>
      2 
      3 inline int nextInt(void) {
      4     register int ret = 0;
      5     register int neg = 0;
      6     register int bit = getchar();
      7     
      8     while (bit < '0') {
      9         if (bit == '-')
     10             neg ^= 1;
     11         bit = getchar();
     12     }
     13     
     14     while (bit >= '0') {
     15         ret = ret*10 + bit - '0';
     16         bit = getchar();
     17     }
     18     
     19     return neg ? -ret : ret;
     20 }
     21 
     22 const int siz = 1000005;
     23 
     24 int n, m, s, col[siz], ans[siz];
     25 
     26 int hd[siz], nt[siz], to[siz], tot;
     27 
     28 int fa[siz][20], dp[siz], dn[siz], tim;
     29 
     30 int sz[siz], bl[siz], cnt, vs[siz], ct[siz], sum;
     31 
     32 void dfs(int u, int f) {
     33     fa[u][0] = f; 
     34     dn[u] = ++tim;
     35     dp[u] = dp[f] + 1; 
     36     
     37     for (int i = 1; i < 20; ++i)
     38         fa[u][i] = fa[fa[u][i - 1]][i - 1];
     39         
     40     for (int i = hd[u]; i; i = nt[i])if (to[i] != f) {
     41         if (sz[bl[u]] < s)
     42             ++sz[bl[to[i]] = bl[u]];
     43         else
     44             ++sz[bl[to[i]] = ++cnt];
     45         dfs(to[i], u);
     46     }
     47 }
     48 
     49 inline int lca(int a, int b) {
     50     if (dp[a] < dp[b])std::swap(a, b);
     51     
     52     for (int i = 19; ~i; --i)
     53         if (dp[fa[a][i]] >= dp[b])
     54             a = fa[a][i];
     55     
     56     if (a == b)return a;
     57     
     58     for (int i = 19; ~i; --i)
     59         if (fa[a][i] != fa[b][i])
     60             a = fa[a][i], b = fa[b][i];
     61     
     62     return fa[a][0];
     63 }
     64 
     65 struct query {
     66     int l, r, a, b, id;
     67     
     68     void read(int i) {
     69         id = i;
     70         l = nextInt();
     71         r = nextInt();
     72         a = nextInt();
     73         b = nextInt();
     74         
     75         if (dn[l] > dn[r])
     76             std::swap(l, r);
     77     }
     78 }qry[siz];
     79 
     80 inline bool cmp_query(const query &A, const query &B) {
     81     if (bl[A.l] != bl[B.l])
     82         return bl[A.l] < bl[B.l];
     83     else
     84         return dn[A.r] < dn[B.r];
     85 }
     86 
     87 inline void change(int t) { 
     88     vs[t] ^= 1;
     89     if (vs[t])
     90         sum += (++ct[col[t]] == 1);
     91     else
     92         sum -= (--ct[col[t]] == 0);
     93 }
     94 
     95 inline void change(int a, int b) {
     96     int L = lca(a, b); 
     97     
     98     while (a != L)
     99         change(a), a = fa[a][0];
    100     
    101     while (b != L)
    102         change(b), b = fa[b][0];
    103 }
    104 
    105 int L, R, LCA;    // Path(L,R) ^ LCA
    106 
    107 inline void solve(const query &q) { 
    108     change(L, q.l); L = q.l;
    109     change(R, q.r); R = q.r;
    110     LCA = lca(L, R);
    111     change(LCA);
    112     ans[q.id] = sum;
    113     if (q.a != q.b)
    114         if (ct[q.a] && ct[q.b])
    115             --ans[q.id];
    116     change(LCA);
    117 }
    118 
    119 signed main(void) {
    120 //    freopen("apple.in", "r", stdin);
    121 //    freopen("apple.out", "w", stdout);
    122     
    123     n = nextInt();
    124     m = nextInt();
    125     
    126     for (int i = 1; i <= n; ++i)
    127         col[i] = nextInt();
    128         
    129     for (int i = 1; i <= n; ++i) {
    130         int x = nextInt();
    131         int y = nextInt();
    132         nt[++tot] = hd[x]; to[tot] = y; hd[x] = tot;
    133         nt[++tot] = hd[y]; to[tot] = x; hd[y] = tot;
    134     }
    135     
    136     L = R = to[hd[0]]; s = sqrt(n);
    137     
    138     sz[bl[0] = cnt = 1] = 1; dfs(0, 0);
    139 
    140     for (int i = 1; i <= m; ++i)qry[i].read(i);
    141     
    142     std::sort(qry + 1, qry + 1 + m, cmp_query);
    143     
    144     for (int i = 1; i <= m; ++i)solve(qry[i]);
    145     
    146     for (int i = 1; i <= m; ++i)printf("%d
    ", ans[i]);
    147 }

    因为BZOJ上已经不再提供测试,submit之后也只能得到RE的结果,只好自己造几个数据,就当AC了。

    @Author: YouSiki

  • 相关阅读:
    DMA详解
    Python实现爬虫设置代理IP和伪装成浏览器的方法(转载)
    Python3 简单验证码识别思路及实例
    Python3 比较两个图片是否类似或相同
    python3 验证码图片切割
    python3 验证码去噪
    Python3 OpenCV应用
    python3 IEDriver抓取时报数据
    Impala 数值函数大全(转载)
    java 获取指定日前的前一天
  • 原文地址:https://www.cnblogs.com/yousiki/p/6155549.html
Copyright © 2011-2022 走看看