• BZOJ3653 谈笑风生


    先对树DFS一边,建立dfs序列

    tr[p].dep表示p的深度,tr[p].sz表示p的子树的大小(不包括p自己)

    对dfs序列建立主席树乱搞= =

    Claris大爷:"线段树中区间[a,b]表示深度在[a,b]范围内的sz的和"

    貌似明白了>_<

    Claris大爷又曰:"查询x,y的答案 = tr[x].sz * min(tr[x].dep, y) + dfs序在tr[x].L + 1到tr[x].R之间且深度在tr[x].dep + 1到tr[x].dep + k之间的sz的和"

    于是就完了2333

      1 /**************************************************************
      2     Problem: 3653
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:9060 ms
      7     Memory:111928 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <algorithm>
     12  
     13 using namespace std;
     14 typedef long long ll;
     15 const int N = 300005;
     16 const int M = 5700000;
     17  
     18 struct edges {
     19     int next, to;
     20     edges() {}
     21     edges(int _next, int _to) : next(_next), to(_to) {}
     22 }e[N << 1];
     23  
     24 struct segment_tree {
     25     ll val;
     26     int lson, rson;
     27 }seg[M];
     28  
     29 struct tree_node {
     30     int fa, dep, sz, L, R;
     31 }tr[N];
     32  
     33 int n, Q;
     34 int D;
     35 int first[N], tot, cnt;
     36 int q[N], TOT, root[N];
     37  
     38 inline int read() {
     39     int x = 0;
     40     char ch = getchar();
     41     while (ch < '0' || '9' < ch)
     42         ch = getchar();
     43     while ('0' <= ch && ch <= '9') {
     44         x = x * 10 + ch - '0';
     45         ch = getchar();
     46     }
     47     return x;
     48 }
     49  
     50 inline void Add_Edges(int x, int y) {
     51     e[++tot] = edges(first[x], y), first[x] = tot;
     52     e[++tot] = edges(first[y], x), first[y] = tot;
     53 }
     54  
     55 void dfs(int p) {
     56     int x, y;
     57     tr[p].L = ++cnt;
     58     q[cnt] = p;
     59     for (x = first[p]; x; x = e[x].next)
     60         if ((y = e[x].to) != tr[p].fa) {
     61             tr[y].fa = p;
     62             tr[y].dep = tr[p].dep + 1;
     63             dfs(y);
     64             tr[p].sz += tr[y].sz + 1;
     65         }
     66     tr[p].R = cnt;
     67 }
     68  
     69 int build(int p, int l, int r, int d, int sz) {
     70     int y = ++TOT;
     71     seg[y].val = seg[p].val + sz;
     72     if (l == r) return y;
     73     int mid = l + r >> 1;
     74     if (d <= mid)
     75         seg[y].lson = build(seg[p].lson, l, mid, d, sz), seg[y].rson = seg[p].rson;
     76     else
     77         seg[y].rson = build(seg[p].rson, mid + 1, r, d, sz), seg[y].lson = seg[p].lson;
     78     return y;       
     79 }
     80  
     81 ll query(int p, int l, int r, int L, int R) {
     82     if (L <= l && r <= R)
     83         return seg[p].val;
     84     int mid = l + r >> 1;
     85     ll res = 0;
     86     if (L <= mid && seg[p].lson)
     87         res += query(seg[p].lson, l, mid, L, R);
     88     if (mid < R && seg[p].rson)
     89         res += query(seg[p].rson, mid + 1, r, L, R);
     90     return res;
     91 }
     92  
     93 inline void print(int x, int y) {
     94     ll a = (ll) tr[x].sz * min(tr[x].dep, y),
     95        b = query(root[tr[x].R], 0, D, tr[x].dep, tr[x].dep + y),
     96        c = query(root[tr[x].L], 0, D, tr[x].dep, tr[x].dep + y);
     97     printf("%lld
    ", (ll) a + b - c);
     98 }
     99  
    100 int main() {
    101     int i, X, Y;
    102     n = read(), Q = read();
    103     for (i = 1; i < n; ++i) {
    104         X = read(), Y = read();
    105         Add_Edges(X, Y);
    106     }
    107     dfs(1);
    108     for (i = 1; i <= n; ++i)
    109         D = max(D, tr[i].dep);
    110     for (i = 1; i <= n; ++i)
    111         root[i] = build(root[i - 1], 0, D, tr[q[i]].dep, tr[q[i]].sz);
    112     while (Q--) {
    113         X = read(), Y = read();
    114         print(X, Y);
    115     }
    116     return 0;
    117 }
    View Code

    (p.s 竟然1WA,蒟蒻简直了。。。还查不错来,要了数据才发现我是沙茶,运算的时候要记得加上"(ll)")

    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    18.9.22 noip模拟赛
    POJ 2299 Ultra-QuickSort
    美团2018年CodeM大赛-初赛B轮 B 配送(最短路)
    Wannafly挑战赛18 E 极差(线段树、单调栈)
    Foj 2299 Prefix(AC自动机、DP)
    求独立矩形个数
    Zoj 3777 Problem Arrangement
    Luogu 2444 [POI2000]病毒 & Zoj 3784
    [ZJOI2007]Hide 捉迷藏
    双联通分量学习笔记
  • 原文地址:https://www.cnblogs.com/rausen/p/4110650.html
Copyright © 2020-2023  润新知