CodeForces 293E Close Vertices 点分治
题意:现在有一棵树,每条边的长度都为1,然后有一个权值,求存在多少个(u,v)点对,他们的路劲长度 <= l, 总权重 <= w.
题解:
1.找到树的重心。
2.求出每个点到中心的长度和权值。
3.对所有点都询问出合法点的个数(包括同一颗子树)加到答案上。
4.对于每一棵子树内部都找到合法点的个数从答案中减去。
5.递归处理每一颗子树。
我们现在最大的问题就是怎么计算合法点的个数。
我们把点的信息记录下来之后,按照权重从小到达排序。
然后我们就可以用2个端点维护出 a[l].weight + a[r].weight <= d
这样对于l来说, [l+1,r]里面的所有点都满足权重的条件了。
然后就只需要询问 [l+1,r]里面的点的深度 <= l - deep[i]的个数了,对于这个个数我们用树状数组去维护这个信息,一开始我们把所有的点的深度都加到树状数组里面,然后每次端点移动位置的时候都把当前点的深度从树状数组中移除,这样我们维护出了一颗[ l+1 , r] 里面的点的深度信息了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 5e5 + ;
int n, len, w;
int tree[N];
int root, sz[N], mxr;
int vis[N];
int head[N], to[N*], nt[N*], ct[N*];
void add(int x, int v){
for(int i = x; i <= n && i; i += i & (-i))
tree[i] += v;
}
int query(int x){
int ret = ;
for(int i = x; i; i -= i&(-i))
ret += tree[i];
return ret;
}
void getW(int o, int u, int num){
sz[u] = ;
int mx = ;
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(vis[v] || v == o) continue;
getW(u, v, num);
sz[u] += sz[v];
mx = max(mx, sz[v]);
}
if(o) mx = max(mx, num-sz[u]);
if(mx < mxr) mxr = mx, root = u;
}
//pll p[N];
struct Node {
int fi, se;
bool operator < (const Node & x) const {
if(fi == x.fi) return se < x.se;
return fi < x.fi;
}
}p[N];
LL cal(int l, int r){
if(l >= r) return ;
sort(p+l, p+r+);
LL ans = ;
for(int i = l; i <= r; i++) add(p[i].se, );
for(int L = l, R = r; L <= R; L++){
while(L < R && p[L].fi + p[R].fi > w) {
add(p[R].se, -);
R--;
}
add(p[L].se, -);
if(L >= R) break;
ans += query(max(, len-p[L].se));
}
return ans;
} int sum = ;
void Dfs(int o, int u, int deep, int w){
sz[u] = ;
++sum;
p[sum].fi = w;
p[sum].se = deep;
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(v == o || vis[v]) continue;
Dfs(u, v, deep+, w+ct[i]);
sz[u] += sz[v];
}
}
LL ans = ;
void GG(int id, int num){
if(num == ){
return ;
}
mxr = inf;
getW(, id, num);
vis[root] = ;
int ls = ; sum = ;
for(int i = head[root]; ~i; i = nt[i]){
int v = to[i];
if(vis[v]) continue;
Dfs(, to[i], , ct[i]);
ans -= cal(ls, sum);
ls = sum + ;
}
sum++;
p[sum].fi = p[sum].se = ;
ans += cal(, sum);
//cout << query(n) << endl;
for(int i = head[root]; ~i; i = nt[i]){
int v = to[i];
if(vis[v]) continue;
GG(v, sz[v]);
}
}
int tot = ;
void add(int u, int v, int w){
to[tot] = v;
ct[tot] = w;
nt[tot] = head[u];
head[u] = tot++;
}
int main(){
memset(head, -, sizeof(head));
scanf("%d%d%d", &n, &len, &w);
int u, v, val;
for(int i = ; i <= n; i++){
u = i;
scanf("%d%d", &v, &val);
add(u, v, val);
add(v, u, val);
}
GG(, n);
printf("%I64d\n", ans);
return ;
}
CodeForces 293E Close Vertices 点分治的更多相关文章
- codeforces 293E Close Vertices
题目链接 正解:点分治+树状数组. 点分治板子题,直接点分以后按照$w$排序,扫指针的时候把$w$合法的路径以$l$为下标加入树状数组统计就行了. 写这道题只是想看看我要写多久..事实证明我确实是老年 ...
- CF 293E Close Vertices——点分治
题目:http://codeforces.com/contest/293/problem/E 仍旧是点分治.用容斥,w的限制用排序+两个指针解决, l 的限制就用树状数组.有0的话就都+1,相对大小不 ...
- Codeforces 293E 点分治+cdq
Codeforces 293E 传送门:https://codeforces.com/contest/293/problem/E 题意: 给你一颗边权一开始为0的树,然后给你n-1次操作,每次给边加上 ...
- ●CodeForce 293E Close Vertices
题链: http://codeforces.com/contest/293/problem/E题解: 点分治,树状数组 大致思路和 POJ 1741 那道点分治入门题相同, 只是因为多了一个路径的边数 ...
- Codeforces 833D Red-Black Cobweb [点分治]
洛谷 Codeforces 思路 看到树上路径的统计,容易想到点分治. 虽然只有一个限制,但这个限制比较麻烦,我们把它拆成两个. 设黑边有\(a\)条,白边有\(b\)条,那么有 \[ 2a\geq ...
- Codeforces 1045G AI robots [CDQ分治]
洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...
- Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]
洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...
- Codeforces 938G Shortest Path Queries [分治,线性基,并查集]
洛谷 Codeforces 分治的题目,或者说分治的思想,是非常灵活多变的. 所以对我这种智商低的选手特别不友好 脑子不好使怎么办?多做题吧-- 前置知识 线性基是你必须会的,不然这题不可做. 推荐再 ...
- Codeforces 526F Pudding Monsters - CDQ分治 - 桶排序
In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...
随机推荐
- 【JDK】JDK源码-Queue, Deque
概述 Queue 和 Deque 都是接口.其中 Queue 接口定义的是一个队列,它包含队列的基本操作:入队(enqueue)和出队(dequeue). Deque 接口继承自 Queue 接口,表 ...
- 【Java】Caused by: com.ibatis.sqlmap.client.SqlMapException: There is no statement named *** in this SqlMap.
如题: 可能原因: 在xxx.xml文件中有两个标签的id命名相同: DAO实现类方法中没有写对应xxx.xml的id名称: 实体映射文件xxx.xml未加入到sqlMap-Config.xml文件中 ...
- Could not launch "APP_NAME" process launch failed: 4294967295
真机调试忽然遇到这个问题, Could not launch "APP_NAME" process launch failed: 如图所示: 模拟器上能正常调试………… 这个问题还 ...
- 详解 git 忽略文件 删除远端仓库的文件
要解决的问题 忽略指定类型的文件 或 某个指定文件(夹) 将已经push到github的文件删除, 但本地的文件不删除 (写忽略规则之前就把这个文件夹push了 T_T ) 将想要忽略掉的文件的相关记 ...
- AUTOSAR学习之RTE - 基本概念
1.什么是RTE? The Run-Time Environment (RTE) is at the heart of the AUTOSAR ECU architecture. The RTE is ...
- Resource 使用详解
极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...
- vue+Elment-UI,修改element组件样式
在用vue开发项目过程中,我们总是避免不了的会使用到elementUI,它里面提供的一些组件都为我们的开发带来了很大的便利,但是,当有时候我们需要使用这些组件的同时又要修改下组件的UI样式的话,我们该 ...
- Vector的一些事
1.利用数组对vector进行初始化方法 当然有许多方法,这里就讲一种.原因简单,其他方式请参见这个博文:http://www.cplusplus.me/1112.html , , , , -}; v ...
- 一文了解:Redis的AOF持久化
Redis的AOF持久化 每当Redis-Server接收到写数据时,就把命令以文本形式追加到AOF文件里,当重启Redis服务时,AOF文件里的命令会被重新执行一次,重新恢复数据.当AOF过大时将重 ...
- java中的各种锁详细介绍
转自:https://blog.csdn.net/axiaoboge/article/details/84335452 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高 ...