首先这个叫"动态点分治",不过瞎YY也能YY出来【比如我。。。

就是记录下点分治的过程和每个点的答案信息,于是查询的时候只要沿着分治好的根一路走下去就行了,于是单次查询的外层复杂度是$O(log n)$的

对于每个点,要记录以从整棵树到它的分治路径和以它为根的子树内权值小于v的点到它的距离和(就是关于权值的前缀和)

于是查询一个点的时候只要二分一下就好了。。。

总复杂度$O((n + Q) * log^2n)$

写了一晚上QAQQQ

 

  1 /**************************************************************
  2     Problem: 4012
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:28756 ms
  7     Memory:107560 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <algorithm>
 12 #include <vector>
 13  
 14 using namespace std;
 15 typedef long long ll;
 16 const int N = 15e4 + 4;
 17  
 18 inline int read();
 19 inline void print(ll);
 20  
 21 struct edge {
 22     int next, to, v;
 23     edge(int _n = 0, int _t = 0, int _v = 0) : next(_n), to(_t), v(_v) {}
 24 } e[N << 1];
 25  
 26 struct data {
 27     int v;
 28     ll dis;
 29     data(int _v = 0, ll _d = 0) : v(_v), dis(_d) {}
 30      
 31     inline bool operator < (const data &p) const {
 32         return v == p.v ? dis < p.dis : v < p.v;
 33     }
 34 };
 35  
 36 struct Path {
 37     int p, s;
 38     ll dis;
 39     Path(int _p = 0, ll _d = 0, int _s = 0) : p(_p), dis(_d), s(_s) {}
 40 };
 41  
 42 struct tree_node {
 43     int v, sz, mx, vis;
 44     vector <Path> path;
 45     vector <data> dis[3];
 46 } tr[N];
 47  
 48 int n, m, mod;
 49 int size, root;
 50 int first[N], tot;
 51 int L, R;
 52 ll ans;
 53  
 54 inline void Add_Edges(int x, int y, int z) {
 55     e[++tot] = edge(first[x], y, z), first[x] = tot;
 56     e[++tot] = edge(first[y], x, z), first[y] = tot;
 57 }
 58  
 59 #define y e[x].to
 60 void get_sz(int p, int fa) {
 61     int x;
 62     tr[p].sz = 1;
 63     for (x = first[p]; x; x = e[x].next)
 64         if (!tr[y].vis && y != fa) {
 65             get_sz(y, p);
 66             tr[p].sz += tr[y].sz;
 67         }
 68 }
 69  
 70 void get_rt(int p, int fa) {
 71     int x;
 72     tr[p].sz = 1, tr[p].mx = 0;
 73     for (x = first[p]; x; x = e[x].next)
 74         if (!tr[y].vis && y != fa) {
 75             get_rt(y, p);
 76             tr[p].sz += tr[y].sz;
 77             tr[p].mx = max(tr[p].mx, tr[y].sz);
 78         }
 79     tr[p].mx = max(tr[p].mx, size - tr[p].sz);
 80     if (tr[p].mx < tr[root].mx) root = p;
 81 }
 82  
 83 void calc(int p, int fa, int tar, int d, int now) {
 84     int x;
 85     tr[p].path.push_back(Path(tar, d, now));
 86     tr[tar].dis[now].push_back(data(tr[p].v, d));
 87     for (x = first[p]; x; x = e[x].next)
 88         if (!tr[y].vis && y != fa)
 89             calc(y, p, tar, d + e[x].v, now);
 90 }
 91  
 92 void work(int p) {
 93     int x, now = 0;
 94     tr[p].vis = 1;
 95     get_sz(p, 0);
 96     tr[p].path.push_back(Path(p, 0, 3));
 97     for (x = first[p]; x; x = e[x].next)
 98         if (!tr[y].vis) calc(y, p, p, e[x].v, now++);
 99     for (x = first[p]; x; x = e[x].next)
100         if (!tr[y].vis) {
101             root = 0, size = tr[y].sz;
102             get_rt(y, 0);
103             work(root);
104         }
105 }
106 #undef y
107  
108 inline ll query(vector <data> *v, ll d, int s) {
109     static ll res;
110     static int i, t;
111     for (i = res = 0; i < 3; ++i) if (i != s) {
112             t = lower_bound(v[i].begin(), v[i].end(), data(L, -1)) - v[i].begin();
113             if (t) res -= d * t + v[i][t - 1].dis;
114             t = lower_bound(v[i].begin(), v[i].end(), data(R + 1, -1)) - v[i].begin();
115             if (t) res += d * t + v[i][t - 1].dis;
116         }
117     return res;
118 }
119  
120 int main() {
121     int i, j, k, x, y, z, Q, p;
122     n = read(), Q = read(), mod = read();
123     for (i = 1; i <= n; ++i) tr[i].v = read();
124     for (i = 1; i < n; ++i) {
125         x = read(), y = read(), z = read();
126         Add_Edges(x, y, z);
127     }
128     tr[root = 0].mx = size = n;
129     get_rt(1, 0);
130     work(root);
131     for (i = 1; i <= n; ++i)
132         for (j = 0; j < 3; ++j) {
133             sort(tr[i].dis[j].begin(), tr[i].dis[j].end());
134             for (k = 1; k < tr[i].dis[j].size(); ++k)
135                 tr[i].dis[j][k].dis += tr[i].dis[j][k - 1].dis;
136         }
137     for (ans = 0; Q; --Q) {
138         p = read(), L = (ans + read()) % mod, R = (ans + read()) % mod;
139         if (L > R) swap(L, R);
140         for (i = ans = 0; i < tr[p].path.size(); ++i) {
141             if (L <= tr[tr[p].path[i].p].v && tr[tr[p].path[i].p].v <= R)
142                 ans += tr[p].path[i].dis;
143             ans += query(tr[tr[p].path[i].p].dis, tr[p].path[i].dis, tr[p].path[i].s);
144         }
145         print(ans);
146     }
147     return 0;
148 }
149  
150 inline int read() {
151     static int x;
152     static char ch;
153     x = 0, ch = getchar();
154     while (ch < '0' || '9' < ch)
155         ch = getchar();
156     while ('0' <= ch && ch <= '9') {
157         x = x * 10 + ch - '0';
158         ch = getchar();
159     }
160     return x;
161 }
162  
163 inline void print(ll t) {
164     static int tot, pr[20];
165     tot = 0;
166     while (t)
167         pr[++tot] = t % 10, t /= 10;
168     if (!tot) putchar('0');
169     while (tot) putchar(pr[tot--] + '0');
170     putchar('\n');
171 }
View Code

 (p.s. bz上AC700T纪念!)

posted on 2015-04-29 22:34  Xs酱~  阅读(988)  评论(0编辑  收藏  举报