• 洛谷P1600 天天爱跑步


    天天放毒...

    首先介绍一个树上差分。

    每次进入的时候记录贡献,跟出来的时候的差值就是子树贡献。

    然后就可以做了。

    发现考虑每个人的贡献有困难。

    于是考虑每个观察员的答案。

    把路径拆成两条,以lca分开。x -> z -> y,完全分成A,B两部分。

    那么A:d[x] = w[z] + d[z];B:len - d[y] + N = w[z] - d[z] + N;

    这里+ N是为了防止负数。

    然后发现右边只跟z有关,这里的z可以是路径上任一点。

    那么对于每个人,把需要树上差分统计的左边数值用vector记录。

    然后跑一遍统计即可。

    注意:如果lca能观测到这条路径,那么--,因为测了A,B两次。

    看代码。

      1 #include <cstdio>
      2 #include <vector>
      3 
      4 const int N = 300010;
      5 
      6 inline void read(int &x) {
      7     x = 0;
      8     char c = getchar();
      9     while(c < '0' || c > '9') {
     10         c = getchar();
     11     }
     12     while(c >= '0' && c <= '9') {
     13         x = (x << 3) + (x << 1) + c - 48;
     14         c = getchar();
     15     }
     16     return;
     17 }
     18 
     19 struct Edge {
     20     int v, nex;
     21 }edge[N << 1]; int top;
     22 
     23 int n, m, e[N], w[N], binA[N << 1], binB[N << 1], cancel[N], d[N], fa[N][20], lm, ans[N];
     24 std::vector<int> vA[N], vB[N], vA_[N], vB_[N];
     25 
     26 inline void add(int x, int y) {
     27     edge[++top].v = y;
     28     edge[top].nex = e[x];
     29     e[x] = top;
     30     return;
     31 }
     32 
     33 void DFS1(int x, int f) {
     34     fa[x][0] = f;
     35     d[x] = d[f] + 1;
     36     for(int i = e[x]; i; i = edge[i].nex) {
     37         int y = edge[i].v;
     38         if(y != f) {
     39             DFS1(y, x);
     40         }
     41     }
     42     return;
     43 }
     44 
     45 inline void getlca() {
     46     DFS1(1, 0);
     47     while((1 << lm) < n) {
     48         lm++;
     49     }
     50     for(int i = 1; i <= lm; i++) {
     51         for(int x = 1; x <= n; x++) {
     52             fa[x][i] = fa[fa[x][i - 1]][i - 1];
     53         }
     54     }
     55     return;
     56 }
     57 
     58 inline int lca(int x, int y) {
     59     int t = lm;
     60     while(d[x] > d[y]) {
     61         std::swap(x, y);
     62     }
     63     while(t > -1 && d[y] > d[x]) {
     64         if(d[fa[y][t]] >= d[x]) {
     65             y = fa[y][t];
     66         }
     67         t--;
     68     }
     69     if(x == y) {
     70         return x;
     71     }
     72     t = lm;
     73     while(t > -1 && fa[x][0] != fa[y][0]) {
     74         if(fa[x][t] != fa[y][t]) {
     75             x = fa[x][t];
     76             y = fa[y][t];
     77         }
     78         t--;
     79     }
     80     return fa[x][0];
     81 }
     82 
     83 void DFS(int x) {
     84     int A = binA[w[x] + d[x]];
     85     int B = binB[w[x] - d[x] + N];
     86     for(int i = e[x]; i; i = edge[i].nex) {
     87         int y = edge[i].v;
     88         if(y != fa[x][0]) {
     89             DFS(y);
     90         }
     91     }
     92     for(int i = 0; i < vA[x].size(); i++) {
     93         binA[vA[x][i]]++;
     94     }
     95     for(int i = 0; i < vB[x].size(); i++) {
     96         binB[vB[x][i]]++;
     97     }
     98     ans[x] += binA[w[x] + d[x]] - A;
     99     ans[x] += binB[w[x] - d[x] + N] - B;
    100     for(int i = 0; i < vA_[x].size(); i++) {
    101         binA[vA_[x][i]]--;
    102     }
    103     for(int i = 0; i < vB_[x].size(); i++) {
    104         binB[vB_[x][i]]--;
    105     }
    106     return;
    107 }
    108 
    109 int main() {
    110     read(n);
    111     read(m);
    112     int x, y, z;
    113     for(int i = 1; i < n; i++) {
    114         read(x);
    115         read(y);
    116         add(x, y);
    117         add(y, x);
    118     }
    119     for(int i = 1; i <= n; i++) {
    120         read(w[i]);
    121     }
    122     getlca();
    123     for(int i = 1; i <= m; i++) {
    124         read(x);
    125         read(y);
    126         z = lca(x, y);
    127         vA[x].push_back(d[x]); //d[x] = w[z] + d[z];
    128         vA_[z].push_back(d[x]); //
    129         int len = d[x] + d[y] - 2 * d[z];
    130         vB[y].push_back(len - d[y] + N); //len - d[y] + N = w[z] - d[z] + N;
    131         vB_[z].push_back(len - d[y] + N);
    132         if(d[x] == w[z] + d[z]) {
    133             cancel[z]++;
    134         }
    135     }
    136 
    137     DFS(1);
    138 
    139     for(int i = 1; i <= n; i++) {
    140         printf("%d ", ans[i] - cancel[i]);
    141     }
    142     /*puts("");
    143     for(int i = 1; i < N * 2; i++) {
    144         if(binB[i]) {
    145             printf("binB[%d] = %d
    ", i, binB[i]);
    146         }
    147         if(binA[i]) {
    148             printf("binA[%d] = %d
    ", i, binA[i]);
    149         }
    150     }
    151     printf("over");*/
    152 
    153     return 0;
    154 }
    AC代码

    zbtrs大佬用主席树A了,还说显然是主席树,太强了%%%

     

  • 相关阅读:
    MYSQL中replace into的用法以及与inset into的区别
    怎么安装phpcms?PHPCMS V9安装图文教程
    Yii 框架生成缩略图
    怎么让普通用户使用root权限执行用户命令
    自学Linux命令的四种方法
    最完整PHP.INI中文版
    前端chrome浏览器调试
    phpstorm快捷键记录
    客户关系管理
    Subquery returns more than 1 row
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9665185.html
Copyright © 2020-2023  润新知