zoukankan      html  css  js  c++  java
  • 洛谷P3241 开店

    题意:紫妹和幽香是17岁的少女,喜欢可爱的东西。

    给定一棵树,有点权,边权。每次求所有权值在[l, r]范围内的点到点x的距离和。强制在线。

    解:动态点分治怎么搞啊......

    一开始想的是权值的限制直接外层权值线段树就行了,关键是怎么批量求距离。

    jxl想的是树上莫队的方法,括号序列。然后发现当x和y在不同子树的时候,x -> lca的距离是负的。

    然后考虑lca。距离是d[x] + d[y] - 2d[lca],前面两个都好求,主要是第三项。

    稍稍思考一下,lca只可能是x到根路径上的点。每个点作为lca的次数就是siz - siz[son]

    所以可以转为计算每条边的贡献。每条边的贡献就是它下面的子树大小。这样就可以做了。

    具体来说,d[x] * cnt和∑d[y]可以用两个前缀和数组求出。以离散化后的权值为下标。

    然后建一个以权值为版本的主席树,线段树上维护的是DFS序的该点的父边的计算次数。

    可以发现,按照权值我们每插入一个点,就要对它到根的路径进行修改。查询的时候也是查询x到根的路径。所以我们必须写树剖了>_<

    主席树区间加区间查,使用标记永久化。

    然后发现我之前以为的标记永久化都是假的......

    具体来说,给一个区间加的时候,它途中经过的区间都要加上相应的值,而标记只打在最后的区间。

    查询的时候,沿途记录标记数量。到终点的时候,用终点的sum + 区间Val * 标记数量即可。

    如果修改在查询上面,那么你会把标记记录下来,最后在终点区间加上。

    如果修改在下,那么你终点区间的sum已经加了那一次修改的影响。

    然后这道毒瘤SB题就这样A了...时间复杂度nlog2n。

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 typedef long long LL;
      5 const int N = 150010, lm = 1e9, M = 30000010;
      6 
      7 struct Edge {
      8     int nex, v, len;
      9 }edge[N << 1]; int tp;
     10 
     11 struct Node {
     12     int val, p;
     13     inline bool operator <(const Node &w) const {
     14         return val < w.val;
     15     }
     16 }node[N];
     17 
     18 int e[N], n, top[N], son[N], fa[N], pos[N], num, siz[N], X[N], deep[N], Sum[N], id[N], val2[N], tot, rt[N], val[N];
     19 LL Val[M], d[N], exVal[N];
     20 int ls[M], rs[M], exsum[N], tag[M];
     21 
     22 inline void add(int x, int y, int z) {
     23     tp++;
     24     edge[tp].v = y;
     25     edge[tp].len = z;
     26     edge[tp].nex = e[x];
     27     e[x] = tp;
     28     return;
     29 }
     30 
     31 void DFS_1(int x, int f) { // siz fa d son
     32     fa[x] = f;
     33     siz[x] = 1;
     34     deep[x] = deep[f] + 1;
     35     for(int i = e[x]; i; i = edge[i].nex) {
     36         int y = edge[i].v;
     37         if(y == f) {
     38             continue;
     39         }
     40         d[y] = d[x] + edge[i].len;
     41         val2[y] = edge[i].len;
     42         DFS_1(y, x);
     43         siz[x] += siz[y];
     44         if(siz[y] > siz[son[x]]) {
     45             son[x] = y;
     46         }
     47     }
     48     return;
     49 }
     50 
     51 void DFS_2(int x, int f) { // pos top
     52     top[x] = f;
     53     pos[x] = ++num;
     54     id[num] = x;
     55     if(son[x]) {
     56         DFS_2(son[x], f);
     57     }
     58     for(int i = e[x]; i; i = edge[i].nex) {
     59         int y = edge[i].v;
     60         if(y == fa[x] || y == son[x]) {
     61             continue;
     62         }
     63         DFS_2(y, y);
     64     }
     65     return;
     66 }
     67 
     68 void Add(int x, int &y, int L, int R, int l, int r) {
     69     if(!y || y == x) {
     70         y = ++tot;
     71         Val[y] = Val[x];
     72         tag[y] = tag[x];
     73         ls[y] = ls[x];
     74         rs[y] = rs[x];
     75         //printf("new %d [%d %d] val = %lld 
    ", y, l, r, Val[y]);
     76     }
     77     Val[y] += Sum[std::min(R, r)] - Sum[std::max(L, l) - 1];
     78     //printf("val %d = %lld  += (%d %d) %d 
    ", y, Val[y], std::min(R, r), std::max(L, l) - 1, Sum[std::min(R, r)] - Sum[std::max(L, l) - 1]);
     79     if(L <= l && r <= R) {
     80         tag[y]++;
     81         return;
     82     }
     83     int mid = (l + r) >> 1;
     84     if(L <= mid) {
     85         Add(ls[x], ls[y], L, R, l, mid);
     86     }
     87     if(mid < R) {
     88         Add(rs[x], rs[y], L, R, mid + 1, r);
     89     }
     90     return;
     91 }
     92 
     93 inline void insert(int x, int id) {
     94     while(x) {
     95         //printf("id = %d 
    ", id);
     96         Add(rt[id - 1], rt[id], pos[top[x]], pos[top[x]] + (deep[x] - deep[top[x]]), 1, n);
     97         x = fa[top[x]];
     98     }
     99     return;
    100 }
    101 
    102 LL Ask(int x, int y, int L, int R, int l, int r, int tagx, int tagy) {
    103     if(L <= l && r <= R) {
    104         return Val[y] - Val[x] + 1ll * (tagy - tagx) * (Sum[r] - Sum[l - 1]);
    105     }
    106     tagx += tag[x];
    107     tagy += tag[y];
    108     int mid = (l + r) >> 1;
    109     LL ans = 0;
    110     if(L <= mid) {
    111         ans += Ask(ls[x], ls[y], L, R, l, mid, tagx, tagy);
    112     }
    113     if(mid < R) {
    114         ans += Ask(rs[x], rs[y], L, R, mid + 1, r, tagx, tagy);
    115     }
    116     return ans;
    117 }
    118 
    119 LL ask(int l, int r, int x) {
    120     LL ans = 0;
    121     while(x) {
    122         LL t = Ask(rt[l - 1], rt[r], pos[top[x]], pos[top[x]] + (deep[x] - deep[top[x]]), 1, n, 0, 0);
    123         ans += t;
    124         x = fa[top[x]];
    125     }
    126     return ans;
    127 }
    128 
    129 int main() {
    130 
    131     //freopen("in.in", "r", stdin);
    132     //freopen("my.out", "w", stdout);
    133 
    134     int q, A;
    135     scanf("%d%d%d", &n, &q, &A);
    136     for(int i = 1; i <= n; i++) {
    137         scanf("%d", &val[i]);
    138         val[i]++;
    139         node[i].p = i;
    140         X[i] = val[i];
    141     }
    142     for(int i = 1, x, y, z; i < n; i++) {
    143         scanf("%d%d%d", &x, &y, &z);
    144         add(x, y, z);
    145         add(y, x, z);
    146     }
    147     // prework
    148 
    149     DFS_1(1, 0);
    150     DFS_2(1, 1);
    151     std::sort(X + 1, X + n + 1);
    152     int temp = std::unique(X + 1, X + n + 1) - X - 1;
    153     for(int i = 1; i <= n; i++) {
    154         val[i] = std::lower_bound(X + 1, X + temp + 1, val[i]) - X;
    155         node[i].val = val[i];
    156         exsum[val[i]]++;
    157         exVal[val[i]] += d[i];
    158     }
    159     for(int i = 1; i <= temp; i++) {
    160         exsum[i] += exsum[i - 1];
    161         exVal[i] += exVal[i - 1];
    162     }
    163     for(int i = 1; i <= n; i++) {
    164         Sum[i] = Sum[i - 1] + val2[id[i]];
    165     }
    166     std::sort(node + 1, node + n + 1);
    167     for(int i = 1; i <= n; i++) {
    168         insert(node[i].p, node[i].val);
    169     }
    170 
    171     LL lastans = 0;
    172     for(int i = 1, x, y, z; i <= q; i++) {
    173         scanf("%d%d%d", &x, &y, &z);
    174         int l = (y + lastans) % A + 1;
    175         int r = (z + lastans) % A + 1;
    176         if(l > r) {
    177             std::swap(l, r);
    178         }
    179         l = std::lower_bound(X + 1, X + temp + 1, l) - X;
    180         r = std::upper_bound(X + 1, X + temp + 1, r) - X - 1;
    181         if(l > r) {
    182             lastans = 0;
    183             printf("%lld
    ", lastans);
    184         }
    185         else {
    186             LL t = ask(l, r, x);
    187             lastans = 1ll * d[x] * (exsum[r] - exsum[l - 1]) + (exVal[r] - exVal[l - 1]);
    188             lastans -= t * 2;
    189             printf("%lld
    ", lastans);
    190         }
    191     }
    192 
    193     return 0;
    194 }
    AC代码
  • 相关阅读:
    pandas Dataframe filter
    process xlsx with pandas
    data manipulate in excel with easyExcel class
    modify registry in user environment
    add number line in vim
    java import webservice
    ctypes MessageBoxA
    music 163 lyrics
    【python实例】自动贩卖机
    【python基础】sys模块(库)方法汇总
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10322135.html
Copyright © 2011-2022 走看看