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 ...
随机推荐
- Ubuntu18.04服务器使用netplan网络构建桥接kvm虚拟机
参考链接 Ubuntu 18.04 LTS安装KVM虚拟机 如何在 Ubuntu 18.04 服务器上安装和配置 KVM KVM日常管理和克隆 KVM详解 1.准备工作 首先需要检查一下CPU是否支持 ...
- 使用vsftp与shell实现对进程与服务状态的监控
先说一下需求吧,公司开发了一款新的产品,新产品嘛,有着不得不出问题的理由,四个云机房,总共三百余台机器,需要实时的监控进程状态,虽然有zabbix来实现,但领导需求是脚本和zabbix一起做,zabb ...
- PHP验证身份证格式
互联网公司对身份证验证的需求越来越多,然而普通的小公司是无法对接公安部门的身份认证系统的.几乎都是在网上买一些大的互联网公司的一些认证服务.即使是便宜一些的认证价格也达到了10万次/万元.也就是一角钱 ...
- python利用select实现的Socket Server
# 利用python的select模块实现简单的Socket Sever #实现多用户访问,再次基础上可以实现FTP Server应用程序 # 发布目的,在于解决了客户端强行终止时,服务器端也跟着程序 ...
- Spring 源码注解
一.@Retention可以用来修饰注解,是注解的注解,称为元注解. Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolic ...
- basic
vmware三种网络类型 bridged(桥接)通过物理主机网卡架设桥,从而连入实际网络,最接近正式网络环境 NAT(地址转换)虚拟机通过宿主机转发地址上网,宿主机ip更改虚拟机不需要改.过程:虚拟机 ...
- CEPH 对象存储的系统池介绍
RGW抽象来看就是基于rados集群之上的一个rados-client实例. Object和pool简述 Rados集群网上介绍的文章很多,这里就不一一叙述,主要要说明的是object和pool.在r ...
- Dialog 使用详解
极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...
- Unity经典游戏教程之:合金弹头
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- Opengl_入门学习分享和记录_00
2019.7.4 本着对游戏创作的热情,本人初步了解了一部分的unity引擎的使用,也学习了一点C#可是越学习unity我就反而对引擎内部感兴趣(不知道有没有一样的朋友=,=). 接着了解到了open ...