Codeforces 293E

传送门:https://codeforces.com/contest/293/problem/E

题意:

给你一颗边权一开始为0的树,然后给你n-1次操作,每次给边加上边权,问你n-1次操作后有有多少对点之间的路径长度小于等于l,并且边权和小于等于w

题解:

poj1741 点分治裸题是 边权和小于等于k,这里加了一个路径条数的限制

对于这个路径条数和边权的两个限制,我们可以得到两个不等式,可以用点分治得到满足距离的一个数组a

将数组a按照距离从小到大排序后,就可以满足cdq的条件了,也是一个三维偏序问题,计数的时候需要注意一下去重

具体解释请看代码注释

代码:

#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
struct node {
int x, y;
int op;
bool operator < (const node &a) const {
if(x != a.x) return x < a.x;
if(y != a.y) return y < a.y;
return op < a.op;
}
node() {};
node(int _x, int _y, int _op) {
x = _x, y = _y, op = _op;
}
} a[maxn], tmp[maxn];
int cnt;
int n, L, W;
struct EDGE {
int v, w, nxt;
} edge[maxn << 1];
int head[maxn];
int tot;
void add_edge(int u, int v, int w) {
edge[tot].v = v;
edge[tot].w = w;
edge[tot].nxt = head[u];
head[u] = tot++;
}
int sz[maxn], vis[maxn], mx[maxn]; int get_root(int u, int fa, int num) {
int y = 0;
mx[u] = 0;
sz[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(!vis[v] && v != fa) {
int z = get_root(v, u, num);
// debug3(u, v, z);
sz[u] += sz[v];
mx[u] = max(mx[u], sz[v]);
if(mx[y] > mx[z]) y = z;
}
}
mx[u] = max(mx[u], num - sz[u]);
return mx[u] < mx[y] ? u : y;
}
void dfs(int u, int fa, int len, int weight) {
a[++cnt] = node(len, weight, 0);//与根节点的距离和权值 当前点 op为0
a[++cnt] = node(L - len, W - weight, 1);//还剩下可以走的距离与权值限制 限制 op为1
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(!vis[v] && v != fa) {
dfs(v, u, len + 1, weight + edge[i].w);
}
}
}
LL cdq(int l, int r) {
if(l == r) return 0;
int mid = (l + r) >> 1;
LL ans = cdq(l, mid) + cdq(mid + 1, r);
int p = l, q = mid + 1, res = 0;
for(int i = l; i <= r; i++) {//因为左边的x已经小于右边的x了,所以只要比较y就行
if((p <= mid && (a[p].y < a[q].y || (a[p].y == a[q].y && a[p].op <= a[q].op))) || q > r) {
res += a[p].op ^ 1;//如果这个点是非限制点,res++
tmp[i] = a[p++];//恢复现场
} else {
ans += a[q].op * res;//如果这个点是限制点,答案就可以增加
tmp[i] = a[q++];
}
}
for(int i = l; i <= r; i++) {
a[i] = tmp[i];
}
// debug3(l, r, ans);
return ans;
}
LL Find(int u, int len, int weight) {
LL res = 0; cnt = 0;
dfs(u, -1, len, weight);//获取a数组,即满足l,w限制的数组
// debug1(cnt);
sort(a + 1, a + cnt + 1);//对x排序
for(int i = 1; i <= cnt; i++) {
if(2 * a[i].x <= L && 2 * a[i].y <= W)
res += a[i].op ^ 1;//不满足条件的,op为0就不满足,
}
// debug1(cnt);
debug1(res);
return (cdq(1, cnt) - res) / 2;//a,b,b,a是一样的,所以除二
}
LL solve(int u, int num) {
int root = get_root(u, -1, num);//点分治 找重心 debug1(root);
cout<<"1"<<endl;
LL res = Find(root, 0, 0);//以该重心分治的贡献
cout<<"root"<<root<<"de gong xian is: ";
debug1(res);
vis[root] = 1;
for(int i = head[root]; i != -1; i = edge[i].nxt) {
int v = edge[i].v, w = edge[i].w;
if(!vis[v]) {
cout<<"2"<<endl;
res -= Find(v, 1, w);//因为这个点是由父亲节点跑过来的,所以边长为1的点重复算了需要减去
// debug1(res);//减去重复的
res += solve(v, sz[v] > sz[root] ? num - sz[root] : sz[v]);//子树大小的判断
}
}
return res;
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
mx[0] = INF;
memset(head, -1, sizeof(head));
tot = 0;
scanf("%d%d%d", &n, &L, &W);
for(int i = 2; i <= n; i++) {
int u, w; scanf("%d%d", &u, &w);
add_edge(i, u, w);
add_edge(u, i, w);
}
printf("%lld\n", solve(1, n));
return 0;
}

Codeforces 293E 点分治+cdq的更多相关文章

  1. Codeforces 1045G AI robots [CDQ分治]

    洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...

  2. Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]

    洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...

  3. Codeforces 526F Pudding Monsters - CDQ分治 - 桶排序

    In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...

  4. CodeForces 293E Close Vertices 点分治

    题目传送门 题意:现在有一棵树,每条边的长度都为1,然后有一个权值,求存在多少个(u,v)点对,他们的路劲长度 <= l, 总权重 <= w. 题解: 1.找到树的重心. 2.求出每个点到 ...

  5. [bzoj] 3263 陌上花开 洛谷 P3810 三维偏序|| CDQ分治 && CDQ分治讲解

    原题 定义一个点比另一个点大为当且仅当这个点的三个值分别大于等于另一个点的三个值.每比一个点大就为加一等级,求每个等级的点的数量. 显然的三维偏序问题,CDQ的板子题. CDQ分治: CDQ分治是一种 ...

  6. UOJ #7 NOI2014购票(点分治+cdq分治+斜率优化+动态规划)

    重写一遍很久以前写过的题. 考虑链上的问题.容易想到设f[i]为i到1的最少购票费用,转移有f[i]=min{f[j]+(dep[i]-dep[j])*p[i]+q[i]} (dep[i]-dep[j ...

  7. codeforces 161D 点分治

    传送门:https://codeforces.com/problemset/problem/161/D 题意: 求树上点对距离恰好为k的点对个数 题解: 与poj1741相似 把点分治的模板改一下即可 ...

  8. 点分治&cdq分治 总结

    游荡的孤高灵魂不需要羁绊之处. 洛谷题单 点分治 前置芝士 树的重心 树分治 例题略解 P3806 [模板]点分治1 板子题,先暴力找到整棵树的重心,然后先求出重心到各点的距离,进而算出他所在树的各个 ...

  9. Codeforces 475D CGCDSSQ(分治)

    题意:给你一个序列a[i],对于每个询问xi,求出有多少个(l,r)对使得gcd(al,al+1...ar)=xi. 表面上是询问,其实只要处理出每个可能的gcd有多少个就好了,当左端点固定的时候,随 ...

随机推荐

  1. 五.获得MYSQL数据库自动生成的主键

    测试脚本如下: 1 create table test1 2 ( 3 id int primary key auto_increment, 4 name varchar(20) 5 ); 测试代码: ...

  2. lower_bounder()和upper_bound()的函数

    lower_bound() .upper_bound()都运用于有序区间的二分查找. ForwardIter lower_bound(ForwardIter first, ForwardIter la ...

  3. 关闭myeclipse可视化视图

    ctrl+w  关闭各个文件  重新打开即可 方法二:

  4. TIJ——Chapter Thirteen:Strings

    String 对象是不可修改的,对于被String 重载的'+' 和'+=' 运算符来说,当你用它们来连接两个String 对象的时候,它在底层并不会对于每一次连接均生成一个String 对象,取而代 ...

  5. Request中getContextPath、getServletPath、getRequestURI、request.getRealPath的区别

    1 区别 假定你的web application 名称为news,你在浏览器中输入请求路径: http://localhost:8080/news/main/list.jsp 1.1 System.o ...

  6. Docker 学习笔记 2019-05-27

    Docker 学习笔记 2019-05-27 可以很方便的打包应用. 使用 docker-compose 更方便. 每个发行版安装方式不一样,如果 centos 直接安装很可能会安装成旧版本. Lin ...

  7. Warning!程序员们小心被技术绑架

    通常我们说程序员需要在某个技术方向上积累到一定的厚度,要能够运用技术有效地解决实际问题.可是当程序员在某一项技术上浸淫时间长了之后,却经常会出现另外的问题,那就是:看待问题时受限于自身的技术积累. 我 ...

  8. 创建ros消息时出现:Unable to load msg [planning/Num]: Cannot locate message [Num]: unknown pack.....

    创建ros消息可参考创建ROS消息和ROS服务. 按照这个教程进行创建的过程中出现了如下错误: Unable to load msg [msgs/locate]: Cannot locate mess ...

  9. android service中stub作用是什么?

    AIDL(android 接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互.如果你需要在一个进程中(例如:在一个Activit ...

  10. Lambda plus: 云上大数据解决方案

    本文会简述大数据分析场景需要解决的技术挑战,讨论目前主流大数据架构模式及其发展.最后我们将介绍如何结合云上存储.计算组件,实现更优的通用大数据架构模式,以及该模式可以涵盖的典型数据处理场景. 大数据处 ...