BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】
题目链接
题解
CDQ分治神题。。。
难想难写。。
比较朴素的思想是对于每个询问都求一遍\(BST\),这样做显然会爆
考虑一下时间都浪费在了什么地方
我们每次求\(BST\)实际上就只有一条边不同,我们实际浪费了很多时间在处理相同的边上
那就考虑分治
对于一个待修改的边集,我们将其权值全部设为\(-\infty\),跑一遍\(BST\),此时其它边如果被选中,说明这些边在单独询问时也一定会被选,将这些边连的点缩点
同样,对于一个待修改的边集,我们将其权值全部设为\(\infty\),跑一遍\(BST\),此时其它边没被选中,说明这些边在单独询问时也一定不会被选,将这些边删掉
这样就可以\(A\)了
复杂度我也不知道是什么
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 50005,maxm = 50005,INF = 0x3fffffff;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct EDGE{int i,a,b,w;}e[50][maxm],d[maxm],b[maxm];
struct Que{int u,v;}q[maxm];
inline bool operator <(const EDGE& a,const EDGE& b){
return a.w < b.w;
}
LL ans[maxm];
int n,m,Q,sum[50],w[maxm],id[maxm],a[maxm];
int pre[maxm];
int find(int u){return u == pre[u] ? u : pre[u] = find(pre[u]);}
void clear(int t){
for (int i = 1; i <= t; i++){
pre[d[i].a] = d[i].a;
pre[d[i].b] = d[i].b;
}
}
void comb(int& t,LL& Ans){
clear(t); int tmp = 0,fa,fb;
sort(d + 1,d + 1 + t);
REP(i,t){
fa = find(d[i].a); fb = find(d[i].b);
if (fa != fb){
pre[fb] = fa;
b[++tmp] = d[i];
}
}
REP(i,tmp) {
pre[b[i].a] = b[i].a;
pre[b[i].b] = b[i].b;
}
REP(i,tmp) if (b[i].w != -INF){
fa = find(b[i].a); fb = find(b[i].b);
if (fa != fb){
pre[fb] = fa;
Ans += b[i].w;
}
}
tmp = 0;
REP(i,t){
fa = find(d[i].a); fb = find(d[i].b);
if (fa != fb){
b[++tmp] = d[i];
id[d[i].i] = tmp;
b[tmp].a = find(b[tmp].a);
b[tmp].b = find(b[tmp].b);
}
}
REP(i,tmp) d[i] = b[i];
t = tmp;
}
void rd(int& t){
clear(t); int tmp = 0,fa,fb;
sort(d + 1,d + 1 + t);
REP(i,t){
fa = find(d[i].a); fb = find(d[i].b);
if (fa != fb){
pre[fb] = fa;
b[++tmp] = d[i];
}
else if (d[i].w == INF){
b[++tmp] = d[i];
}
}
for (int i = 1; i <= tmp; i++) d[i] = b[i];
t = tmp;
}
void solve(int l,int r,int now,LL Ans){
int t = sum[now];
if (l == r) a[q[l].u] = q[l].v; //原标号边权值
for (int i = 1; i <= t; i++)
e[now][i].w = a[e[now][i].i]; //边赋值
for (int i = 1; i <= t; i++)
d[i] = e[now][i],id[d[i].i] = i; //新边对应旧边位置
if (l == r){
ans[l] = Ans; clear(t);
sort(d + 1,d + 1 + t);
int fa,fb;
for (int i = 1; i <= t; i++){
fa = find(d[i].a); fb = find(d[i].b);
if (fa != fb){
pre[fb] = fa; ans[l] += d[i].w;
}
}
return;
}
for (int i = l; i <= r; i++) d[id[q[i].u]].w = -INF;
comb(t,Ans);
for (int i = l; i <= r; i++) d[id[q[i].u]].w = INF;
rd(t);
REP(i,t) e[now + 1][i] = d[i];
sum[now + 1] = t;
int mid = l + r >> 1;
solve(l,mid,now + 1,Ans);
solve(mid + 1,r,now + 1,Ans);
}
int main(){
n = read(); m = read(); Q = read();
for (int i = 1; i <= m; i++){
e[0][i].i = i;
e[0][i].a = read();
e[0][i].b = read();
a[i] = e[0][i].w = read();
}
for (int i = 1; i <= Q; i++){
q[i].u = read();
q[i].v = read();
}
sum[0] = m;
solve(1,Q,0,0);
for (int i = 1; i <= Q; i++)
printf("%lld\n",ans[i]);
return 0;
}
BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】的更多相关文章
- BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治
2001: [Hnoi2010]City 城市建设 Time Limit: 20 Sec Memory Limit: 162 MB Description PS国是一个拥有诸多城市的大国,国王Lou ...
- BZOJ2001: [Hnoi2010]City 城市建设
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2001 cdq分治+重建图. 可以保留当前一定会被选的非修改边然后把点缩起来.这样的话每次点数至 ...
- bzoj 2001 CITY 城市建设 cdq分治
题目传送门 题解: 对整个修改的区间进行分治.对于当前修改区间来说,我们对整幅图中将要修改的边权都先改成-inf,跑一遍最小生成树,然后对于一条树边并且他的权值不为-inf,那么这条边一定就是树边了. ...
- 【BZOJ2001】 [Hnoi2010]City 城市建设
BZOJ2001 [Hnoi2010]City 城市建设 Solution 我们考虑一下这个东西怎么求解? 思考无果...... 咦? 好像可以离线cdq,每一次判断一下如果这条边如果不选就直接删除, ...
- BZOJ 2001: [Hnoi2010]City 城市建设
2001: [Hnoi2010]City 城市建设 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1132 Solved: 555[Submit][ ...
- 【bzoj2001】 Hnoi2010—City 城市建设
http://www.lydsy.com/JudgeOnline/problem.php?id=2001 (题目链接) 题意 给出一张无向图,$m$组操作,每次修改一条边的权值,对于每次操作输出修改之 ...
- bzoj 2001: City 城市建设 cdq
题目 PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁.Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费.Louis希望建造最少的道路使得国内所有 ...
- [HNOI2010]CITY 城市建设
问题: 给一张图,支持边长度修改,求MST 题解: 自己想就想不到了.. 考虑cdq分治 1.首先求出一定有用的边 对于未处理的边,全部设为-INF,求一次MST,出现在MST上的边一定最终出现在后面 ...
- 2001: [Hnoi2010]City 城市建设 - BZOJ
DescriptionPS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁.Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费.Louis希望建造最少的 ...
随机推荐
- 【Java】Spring MVC 扩展和SSM框架整合
开发web项目通常很多地方需要使用ajax请求来完成相应的功能,比如表单交互或者是复杂的UI设计中数据的传递等等.对于返回结果,我们一般使用JSON对象来表示,那么Spring MVC中如何处理JSO ...
- 登録更新(BAPI)
購買管理(MM) * [BAPI_REQUISITION_CREATE] 購買依頼登録 * [BAPI_REQUISITION_CHANGE] 購買依頼変更 * [BAPI_REQUISITION_D ...
- JENKINS系统的安装部署
JENKINS 安装使用文档 简介 Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台.这是一个免费的源代码,可以处理任何类型的构建或持续集成,集成Jenkins可 ...
- 永无BUG 注释
/** * _ooOoo_ * o8888888o * 88" . "88 ...
- P1855 榨取kkksc03
P1855 榨取kkksc03 题目描述 以下皆为真实的故事. 洛谷2的团队功能是其他任何oj和工具难以达到的.借助洛谷强大的服务器资源,任何学校都可以在洛谷上零成本的搭建oj并高效率的完成训练计划. ...
- 常用操作提高效率 之 for 与in
问题如何而来: 对于刚参加工作的我 批量删除数据通常采用的是前端传递到后台一个对象的id字符串 通过逗号分隔的多个id 或者收的直接是一个id数组 两个原理一样第一个后台要在次使用split(& ...
- SQL Server 2005 导出包含(insert into)数据的SQL脚本 (使用存储过程) 分类: 数据库
CREATE PROCEDURE dbo.UspOutputData @tablename sysname AS ) ) ) declare @xtype tinyint declare @name ...
- 读取Excel错误,未在本地计算机上注册 oledb.4.0
以前写的一个读取Excel的程序,现在在另外一台机器上运行,竟然报错说"未在本地计算机上注册 oledb.4.0" 最后才知道,原来是因为现在运行的那台电脑 ...
- 【Luogu P4644】Cleaning Shifts
题目 给定 \(n\) 个区间 \([a_i, b_i]\), 花费为 \(c_i\), 求覆盖 \([L, R]\) 区间的所有整数的最小花费. \(0\le n \le 10^4, 0\le L, ...
- 国际电话区号SQL
CREATE TABLE `phone_prefix` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `country` varchar(30) N ...