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 }

时间: 2024-10-10 21:52:16

codeforces293E (树上点分治+树状数组)的相关文章

HDU 5618:Jam&#39;s problem again(CDQ分治+树状数组处理三维偏序)

http://acm.hdu.edu.cn/showproblem.php?pid=5618 题意:-- 思路:和NEUOJ那题一样的.重新写了遍理解了一下,算作处理三维偏序的模板了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 #d

BZOJ 2683 简单题 cdq分治+树状数组

题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后,二维的数据结构是显然不能过的,于是我们可能会考虑把一维排序之后另一位上数据结构什么的,然而cdq分治却能够很好的体现它的作用. 首先,对于每一个询问求和,显然是x在它左边的并且出现时间在它之前的所有的change对他可能会有影响. 我们按照x第一关键字,y第二关键字,操作第三关键字来排序所有的询问,然后在cdq的时候,每次递归处理左半区间,按照x动态的将y这一列的值加到树状数组里,来更新右半边的所有询问,注意这

XJOI NOIP2015模拟赛Day1 T2 ctps bitset优化 或 排序+cdq分治+树状数组+平衡树

题意: 4维空间中有1个点集A,|A|=n,用(a,b,c,d)表示每个点. 共有m个询问,每次询问输入一个点(a,b,c,d),求最大的S,其中S={p|p∈A且ap<=a,bp<=b,cp<=c,dp<=d},输出|S| 输入格式: 第一行n 接下来n行有n个4维点对 第n+2行有一个数m 再接下来m行每行有一个四维点对,表示每个询问 输出格式: 对于每个询问输出一个数 **方法:**bitset优化 或 排序+cdq分治+树状数组+平衡树 解析: 神题,考场不会,暴力骗40,

【BZOJ4553】[Tjoi2016&amp;Heoi2016]序列 cdq分治+树状数组

[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可.注意:每种变化最多只有一个值发生变化.在样例输入1中,所有的变化是: 1 2 3 2 2 3 1 3 3 1

BZOJ2683: 简单题(CDQ分治 + 树状数组)

BZOJ2683: 简单题(CDQ分治 + 树状数组) 题意: 你有一个\(N*N\)的棋盘,每个格子内有一个整数,初始时的时候全部为\(0\),现在需要维护两种操作: 命令 参数限制 内容 \(1\ x\ y\ A\) \(1\le x,y \le N\),A是正整数 将格子\(x,y\)里的数字加上\(A\) \(2\ x1\ y1\ x2\ y2\) \(1\le x1\le x2\le N,1\le y1\le y2\le N\) 输出\(x1\ y1\ x2\ y2\)这个矩形内的数字

【BZOJ2870】最长道路tree 点分治+树状数组

[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来往,所以每个路口i都有一个拥挤程度v[i],我们认为从路口s走到路口t的痛苦程度为s到t的路径上拥挤程度的最小值,乘上这条路径上的路口个数所得的积.现在请你求出痛苦程度最大的一条路径,你只需输出这个痛苦程度. 简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积

【HDU】4918 Query on the subtree 点分治+树状数组

传送门:[HDU]4918 Query on the subtree 题目分析: 首先,简化问题. 1.求一次到点u的距离不超过d的点的个数.很容易,一次O(NlogN)的点分治便可以完成. 2.多次进行操作1.此时不能每次都O(NlogN)了,太慢了.我们考虑到对于点分治,树的重心一共有logN层,第一层为整棵树的重心,第二层为第一层重心的子树的重心,以此类推,每次至少分成两个大小差不多的子树,所以一共有logN层.而且,对于一个点,他最多只属于logN个子树,也就是最多只属于logN个重心.

SPOJ - FTOUR2 (点分治+树状数组)

题目:https://vjudge.net/contest/307753#problem/I 题意:有一颗树,上面有白色黑色点,每个点上有一个权值,权值可以为负,现在我要求一条路径,权值和最大,这条路径满足  白色可以随便经过多少个,黑色点的个数必须<=m 思路:首先又是树上路径题,必然点分治,其实这个题我们在考虑当前子树路径时,我们找前面子树出现过并且黑色出现数<=m-当前黑色节点数 里面出现的最大值这样的一条路径. 举个栗子:    限制路径黑色数:5 当前子树下的黑色数 :2  权值 

BZOJ1176---[Balkan2007]Mokia (CDQ分治 + 树状数组)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1176 CDQ第一题,warush了好久.. CDQ分治推荐论文: 1 <从<Cash>谈一类分治算法的应用> 陈丹琦 2 <浅谈数据结构题的几个非经典解法>  许昊然 关于CDQ分治,两种要求:①操作不相互影响  ②可以离线处理 题目描述是有问题的,,初始时 全部为0,不是s 题意:二维平面内,两种操作,1 x y v ,位于(x,y)的值加上v...2 x1,