zoukankan      html  css  js  c++  java
  • [COGS 2258][HZOI 2015]复仇的序幕曲

    Description

    你还梦不梦痛不痛,回忆这么重你怎么背得动 ----序言

    当年的战火硝烟已经渐渐远去,可仇恨却在阿凯蒂王子的心中越来越深

    他的叔父三年前谋权篡位,逼宫杀死了他的父王,用铁血手腕平定了国内所有的不满

    只有他一个人孤身逃了出来,而现在他组织了一只强大的军队,反攻的号角已经吹响

    大战一触即发,作为他的机智又勇敢的指挥官,你必须要准确及时的完成他布置的任务

    这个国家的布局是一棵树,每个城市都是树上的结点,其中每个结点上都有军队ai(人数)

    树上的每条边有边权wi,表示通过这条边所需要的时间

    当一个城市u受到攻击时,所有城市的军队都会同时向这个城市移动

    阿凯蒂王子需要知道在时间T内,u城市最多聚集多少人

    Input

    第一行n,m,分别表示城市数目和询问次数

    第二行有n个正整数,表示每个结点军队人数ai

    以下n-1行每行描述树上的一条边的两个端点u,v和边权w

    以下m行每行一个询问u,T

    表示在时间T内,u城市最多聚集多少人

    注意询问之间相互独立

    Output

    输出m行,每行一个数

    表示询问的答案

    Sample Input

    5 5

    3 7 1 7 4

    2 1 9

    3 1 6

    4 2 5

    5 3 1

    5 1

    4 3

    1 1

    1 4

    4 2

    Sample Output

    5

    7

    3

    3

    7

    Hint

    n<=80000,m<=80000

    边权和军队人数均<=1000

    题解

    首先,对于题目要求 $dist(u, v) leq k$ ,我们从 $u$ 在点分树向上跳的时候,第一次处理到含点 $v$ 的重心,那么这个重心就是 $lca(u, v)$ ,我们对这个 $lca$ 进行处理。

    由于满足上式,所以 $dist(u, lca)+dist(v, lca) leq k$ 等价于若点 $v$ 满足 $dist(v, lca) leq k-dist(u, lca)$ 那么显然 $v$ 是满足 $u$ 。

    那么我们可以在每个节点上建一棵平衡树,维护以其为重心的子树中 $dist(v, lca)$ 的值,显然统计答案就是平衡树中 $leq k-dist(u, lca)$ 的个数。

    按照套路,为了防止重复计算,我们需要减去会在这个重心的父亲处重复计算的值。记在点分树中 $u$ 节点的父亲为 $fa_u$ ,所以我们再开一个平衡树来存 $dist(fa_{lca}, v)$ ,额外减去的就是第二棵平衡树中 $leq k-dist(fa_{lca}, u)$ 的个数。

      1 //It is made by Awson on 2018.1.19
      2 #include <set>
      3 #include <map>
      4 #include <cmath>
      5 #include <ctime>
      6 #include <queue>
      7 #include <stack>
      8 #include <cstdio>
      9 #include <string>
     10 #include <vector>
     11 #include <cstdlib>
     12 #include <cstring>
     13 #include <iostream>
     14 #include <algorithm>
     15 #define LL long long
     16 #define Abs(a) ((a) < 0 ? (-(a)) : (a))
     17 #define Max(a, b) ((a) > (b) ? (a) : (b))
     18 #define Min(a, b) ((a) < (b) ? (a) : (b))
     19 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
     20 #define writeln(x) (write(x), putchar('
    '))
     21 using namespace std;
     22 const int N = 80000;
     23 const int INF = ~0u>>1;
     24 void read(int &x) {
     25     char ch; bool flag = 0;
     26     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
     27     for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
     28     x *= 1-2*flag;
     29 }
     30 void write(int x) {
     31     if (x > 9) write(x/10);
     32     putchar(x%10+48);
     33 }
     34 
     35 int val[N+5], n, m, u, v, fa[N+5], last, c;
     36 struct tt {int to, next, cost; }edge[(N<<1)+5];
     37 int path[N+5], top;
     38 void add(int u, int v, int c) {
     39     edge[++top].to = v, edge[top].next = path[u], edge[top].cost = c, path[u] = top;
     40 }
     41 struct Treap {
     42     int root[N+5], key[N*30+5], val[N*30+5], sum[N*30+5], lev[N*30+5], ch[N*30+5][2], pos;
     43     void newnode(int &o, int keyy, int vall) {
     44     o = ++pos;
     45     key[o] = keyy, sum[o] = val[o] = vall, lev[o] = rand(), ch[o][0] = ch[o][1] = 0;
     46     }
     47     void pushup(int o) {sum[o] = sum[ch[o][0]]+sum[ch[o][1]]+val[o]; }
     48     void rotate(int &o, int kind) {
     49     int x = ch[o][!kind];
     50     ch[o][!kind] = ch[x][kind];
     51     ch[x][kind] = o;
     52     o = x;
     53     }
     54     void insert(int &o, int keyy, int vall) {
     55     if (!o) {newnode(o, keyy, vall); return; }
     56     sum[o] += vall; int kind = keyy >= key[o];
     57     insert(ch[o][kind], keyy, vall);
     58     if (lev[ch[o][kind]] < lev[o]) rotate(o, !kind), pushup(ch[o][!kind]), pushup(o);
     59     }
     60     int query(int o, int keyy) {
     61      if (!o) return 0;
     62     if (keyy >= key[o]) return sum[ch[o][0]]+val[o]+query(ch[o][1], keyy);
     63     return query(ch[o][0], keyy);
     64     }
     65 }T1, T2;
     66 namespace LCA {
     67     int log2[(N<<1)+5], bin[25], f[(N<<1)+5][25], dfn[N+5], tim;
     68     void dfs(int o, int cost) {
     69     f[dfn[o] = ++tim][0] = cost;
     70     for (int i = path[o]; i; i = edge[i].next)
     71         if (!dfn[edge[i].to]) dfs(edge[i].to, cost+edge[i].cost), f[++tim][0] = cost;
     72     }
     73     int query(int x, int y) {
     74     if (dfn[x] > dfn[y]) Swap(x, y); int lim = log2[dfn[y]-dfn[x]+1];
     75     return Min(f[dfn[x]][lim], f[dfn[y]-bin[lim]+1][lim]);
     76     }
     77     int dist(int x, int y) {return f[dfn[x]][0]+f[dfn[y]][0]-(query(x, y)<<1); }
     78     void main() {
     79     bin[0] = 1, log2[0] = -1;
     80     for (int i = 1; i <= (n<<1); i++) log2[i] = log2[i>>1]+1;
     81     for (int i = 1; i <= 20; i++) bin[i] = bin[i-1]<<1;
     82     dfs(1, 0);
     83     for (int t = 1; t <= log2[n<<1]; t++) for (int i = 1; i+bin[t]-1 <= (n<<1); i++) f[i][t] = Min(f[i][t-1], f[i+bin[t-1]][t-1]);
     84     }
     85 }
     86 namespace Point_divide {
     87     int size[N+5], mx[N+5], minsize, root, vis[N+5];
     88     void get_root(int o, int pa, int fa) {
     89     mx[o] = Max(mx[o], size[pa]-size[o]);
     90     if (mx[o] < minsize) minsize = mx[o], root = o;
     91     for (int i = path[o]; i; i = edge[i].next)
     92         if (edge[i].to != fa && !vis[edge[i].to]) get_root(edge[i].to, pa, o);
     93     }
     94     void get_size(int o, int fa) {
     95     size[o] = 1, mx[o] = 0;
     96     for (int i = path[o]; i; i = edge[i].next)
     97         if (edge[i].to != fa && !vis[edge[i].to]) {
     98         get_size(edge[i].to, o);
     99         size[o] += size[edge[i].to];
    100         if (size[edge[i].to] > mx[o]) mx[o] = size[edge[i].to];
    101         }
    102     }
    103     void get_insert(int o, int pa, int da, int fa, int cost) {
    104     T1.insert(T1.root[da], cost, val[o]); if (pa) T2.insert(T2.root[da], LCA::dist(pa, o), val[o]);
    105     for (int i = path[o]; i; i = edge[i].next) if (edge[i].to != fa && !vis[edge[i].to]) get_insert(edge[i].to, pa, da, o, cost+edge[i].cost);
    106     }
    107     void work(int o, int pa) {
    108     minsize = INF; get_size(o, 0), get_root(o, o, 0); vis[root] = 1, fa[root] = pa; int rt = root;
    109     T1.insert(T1.root[root], 0, val[root]); if (pa) T2.insert(T2.root[root], LCA::dist(pa, root), val[root]);
    110     for (int i = path[root]; i; i = edge[i].next)
    111         if (!vis[edge[i].to]) get_insert(edge[i].to, pa, root, 0, edge[i].cost);
    112     for (int i = path[root]; i; i = edge[i].next)
    113         if (!vis[edge[i].to]) work(edge[i].to, rt);
    114     }
    115     void main() {work(1, 0); }
    116 }
    117 
    118 int query(int o, int k) {
    119     int ans = 0;
    120     for (int x = o; x; x = fa[x]) {
    121     ans += T1.query(T1.root[x], k-LCA::dist(x, o));
    122     if (fa[x]) ans -= T2.query(T2.root[x], k-LCA::dist(fa[x], o));
    123     }
    124     return ans;
    125 }
    126 void work() {
    127     srand(time(0)); read(n), read(m);
    128     for (int i = 1; i <= n; i++) read(val[i]);
    129     for (int i = 1; i < n; i++) {read(u), read(v), read(c); add(u, v, c), add(v, u, c); }
    130     LCA::main(); Point_divide::main();
    131     while (m--) {
    132     read(u), read(v); writeln(query(u, v));
    133     }
    134 }
    135 int main() {
    136     work();
    137     return 0;
    138 }
  • 相关阅读:
    ArrayList类?
    Spring事务管理?
    Collection集合?
    Scanner类?
    定义三个int类型变量c,d,e. 求出三个变量的最大值,并打印出来?
    定义一个三位整数,请分别获取该三位数上每一位的数值 ?
    Collection集合和Map集合的区别?
    UITableView不错的资源大全
    几个新的开源框架
    一个错误Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x4b3c2a0> setValue:forUndefinedKey:]: this class i
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8315282.html
Copyright © 2011-2022 走看看