codeforces293E (树上点分治+树状数组)

和poj1747相比起来,只不过是限制条件多了一维。 

而多了这一维,所以需要用树状数组来维护,从而快速得到答案。

因为没注意传进树状数组函数的参数可能是<=0的,导致超时了好久。

  1 #pragma warning(disable:4996)
  2 #pragma comment(linker, "/STACK:1024000000,1024000000")
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <time.h>
  6 #include <math.h>
  7 #include <map>
  8 #include <set>
  9 #include <queue>
 10 #include <stack>
 11 #include <vector>
 12 #include <bitset>
 13 #include <algorithm>
 14 #include <iostream>
 15 #include <string>
 16 #include <functional>
 17 const int INF = 1 << 30;
 18 typedef __int64 LL;
 19 /**/
 20 const int N = 100000 + 10;
 21 
 22 int n, L, W;
 23 struct Edge
 24 {
 25     int to, dis, next;
 26 }g[N*2];
 27 struct Node
 28 {
 29     int l, w;
 30     bool operator<(const Node&rhs)const
 31     {
 32         return w < rhs.w;
 33     }
 34 }a[N];
 35 int head[N], e;
 36 int tree[N];
 37 int size[N], p, total, mins, root;
 38 bool vis[N];
 39 LL ans;
 40 int maxL;
 41 int lowbit(int x)
 42 {
 43     return x &(-x);
 44 }
 45 
 46 //树状数组如果pos<=0,那么会死循环, 卡这里超时了好久。
 47 void modify(int pos, int val)
 48 {
 49     pos += 1;
 50     while (pos <= maxL+1)
 51     {
 52         tree[pos] += val;
 53         pos += lowbit(pos);
 54     }
 55 }
 56 int getSum(int pos)
 57 {
 58     pos += 1;
 59     if (pos <= 0) return 0;
 60     int ret = 0;
 61     while (pos > 0)
 62     {
 63         ret += tree[pos];
 64         pos -= lowbit(pos);
 65     }
 66     return ret;
 67 }
 68 
 69 void addEdge(int u, int v, int dis)
 70 {
 71     g[e].to = v;
 72     g[e].dis = dis;
 73     g[e].next = head[u];
 74     head[u] = e++;
 75 }
 76 
 77 void getRoot(int u, int fa)
 78 {
 79     int maxs = 0;
 80     size[u] = 1;
 81     for (int i = head[u];i != -1;i = g[i].next)
 82     {
 83         int v = g[i].to;
 84         if (v == fa || vis[v]) continue;
 85         getRoot(v, u);
 86         size[u] += size[v];
 87         maxs = std::max(maxs, size[v]);
 88     }
 89     maxs = std::max(maxs, total - size[u]);
 90     if (mins > maxs)
 91     {
 92         mins = maxs;
 93         root = u;
 94     }
 95 }
 96 void getA(int u, int fa, int l, int w)
 97 {
 98     a[p].l = l;
 99     a[p++].w = w;
100     maxL = std::max(maxL, l);
101     for (int i = head[u];i != -1;i = g[i].next)
102     {
103         int v = g[i].to;
104         if (v == fa || vis[v]) continue;
105         getA(v, u, l + 1, w + g[i].dis);
106     }
107 }
108 
109 LL counts(int u, int ll, int ww)
110 {
111     p = 0;
112     maxL = 0;
113     getA(u, -1, ll, ww);
114     std::sort(a, a + p);
115     int l = 0, r = p - 1;
116     LL ret = 0;
117     while (l < r &&a[l].w + a[r].w>W)
118         r--;
119     if (l < r)
120     {
121         for (int i = l+1;i <= r;++i)
122             modify(a[i].l,1);
123         while (l < r)
124         {
125             if (a[l].w + a[r].w <= W)
126             {
127                 ret += getSum(std::min(L - a[l].l,maxL));
128                 l++;
129                 modify(a[l].l,-1);
130             }
131             else
132             {
133                 modify(a[r].l,-1);
134                 r--;
135             }
136         }
137     }
138     return ret;
139 }
140 
141 void go(int u)
142 {
143     vis[u] = true;
144     ans += counts(u, 0, 0);
145     for (int i = head[u];i != -1;i = g[i].next)
146     {
147         int v = g[i].to;
148         if (vis[v]) continue;
149         ans -= counts(v, 1, g[i].dis);
150         mins = INF;
151         total = size[v];
152         getRoot(v, -1);
153         go(root);
154     }
155 }
156 int main()
157 {
158     scanf("%d%d%d", &n, &L, &W);
159     
160     int u, v, dis;
161     memset(head, -1, sizeof(head));
162     for (int i = 1;i < n;++i)
163     {
164         u = i + 1;
165         scanf("%d%d", &v, &dis);
166         addEdge(u, v, dis);
167         addEdge(v, u, dis);
168     }
169     mins = INF;
170     total = n;
171     getRoot(1, -1);
172     go(root);
173     printf("%I64d
", ans);
174     
175     return 0;
176 }
View Code
原文地址:https://www.cnblogs.com/justPassBy/p/4769820.html