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 ...
随机推荐
- ERROR 临时
ERROR ITMS-4238: "Redundant Binary Upload. There already exists a binary upload with build vers ...
- 华为matebook14vm虚拟机错误
1.创建时显示不支持64位虚拟机 测试环境: 华为matebook14 window10 专业工作站版 1903 问题描述: 创建虚拟机时显示:此主机不支持64位解决方案 问题参考: 参考1 ...
- 机房ping监控 smokeping+prometheus+grafana(续) 自动获取各省省会可用IP
一.前言 1.之前的文章中介绍了如何使用smokeping监控全国各省的网络情况:https://www.cnblogs.com/MrVolleyball/p/10062231.html 2.由于之前 ...
- JavaScript数据结构——链表的实现与应用
链表用来存储有序的元素集合,与数组不同,链表中的元素并非保存在连续的存储空间内,每个元素由一个存储元素本身的节点和一个指向下一个元素的指针构成.当要移动或删除元素时,只需要修改相应元素上的指针就可以了 ...
- Broadcast 使用详解
极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...
- Java | Map排序,工具类改进
package util; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; ...
- 前端笔记之微信小程序(二){{}}插值和MVVM模式&数据双向绑定&指令&API
一.双花括号{{}}插值和MVVM模式 1.1 体会{{}}插值 index.wxml的标签不是html的那些标签,这里的view就是div. {{}}这样的插值写法,叫做mustache语法.mus ...
- DedeCMS V5.7 SP2前台文件上传漏洞(CVE-2018-20129)
DedeCMS V5.7 SP2前台文件上传漏洞(CVE-2018-20129) 一.漏洞描述 织梦内容管理系统(Dedecms)是一款PHP开源网站管理系统.Dedecms V5.7 SP2版本中的 ...
- 安装Windows Server 2008
下面介绍一下,Windows Server操作系统安装,以及在企业中的应用,在小型企业中可以使用不同的版本搭建不同类型的服务,小型企业中可以搭建Web服务,FTP服务,以及DNS和DHCP服务等,在大 ...
- JavaWeb无框架,借助反射采用精巧设计模式实现放微信PC聊天页面
本周开始在写仿写一个微信PC端的聊天页面,没有使用ssh.ssm等框架,采用JavaWeb.反射.MySQL.C3P0等技术.这里把其中和核心技术列出来请大家指教. 与传统JavaWeb项目的区别 传 ...