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\n", ans); 174 175 return 0; 176 }