2001: [Hnoi2010]City 城市建设

Time Limit: 20 Sec  Memory Limit: 162 MB

Description

PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁。Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费。Louis希望建造最少的道路使得国内所有的城市连通。但是由于某些因素,城市之间修建道路需要的花费会随着时间而改变,Louis会不断得到某道路的修建代价改变的消息,他希望每得到一条消息后能立即知道使城市连通的最小花费总和, Louis决定求助于你来完成这个任务。

Input

文件第一行包含三个整数N,M,Q,分别表示城市的数目,可以修建的道路个数,及收到的消息个数。 接下来M行,第i+1行有三个用空格隔开的整数Xi,Yi,Zi(1≤Xi,Yi≤n, 0≤Zi≤50000000),表示在城市Xi与城市Yi之间修建道路的代价为Zi。接下来Q行,每行包含两个数k,d,表示输入的第k个道路的修建代价修改为d(即将Zk修改为d)。

Output

输出包含Q行,第i行输出得知前i条消息后使城市连通的最小花费总和。

Sample Input

5 5 3
1 2 1
2 3 2
3 4 3
4 5 4
5 1 5
1 6
1 1
5 3

Sample Output

14
10
9

HINT

【数据规模】 对于20%的数据, n≤1000,m≤6000,Q≤6000。 有20%的数据,n≤1000,m≤50000,Q≤8000,修改后的代价不会比之前的代价低。 对于100%的数据, n≤20000,m≤50000,Q≤50000。

(转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/8028462.html )

想法题……太神了
最暴力的当然是$O(n^{2}logn)$的暴力,但是这样操作的次数就太多了,我们需要优化
或者优化每次的边数,或者优化操作的次数
优化操作次数显然是不行的……
我们会发现,有一些“绝对不可能成为最优解”的边在暴力里被重复排序了
那么我们可以直接把他们删掉,来减少这种影响。
另外,有一些“绝对存在于最优解中“的边,我们预先计入他们的值,并在边集中去除它们并缩点
这样我们就有了分治的思路,对”每个修改操作控制的时间“分治

代码打起来倒不是很长……
两份代码是两种实现方法,第一份来自FoolMike神犇……是上面说的按时间分治,比较优秀
只有存在时间完全覆盖了l~r这个时间段的边才存在,
并且有缩点和删边2个优化操作。
至于第二份……是自己打的,每次把这段时间内被修改的边标记成+inf和-inf,+inf时没被选上的边是要删去的,
-inf时被选上的边是要必须选的。优化没有打好,也就比暴力强一点……
这份代码是给自己存着解闷的,想研究程序的请看第一份23333

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define inf 50000001
#define N 20010
#define M 50010
#define LL long long
char B[<<],*cS=B,*cT=B;
#define getc (cS==cT&&(cT=(cS=B)+fread(B,1,1<<15,stdin),cS==cT)?0:*cS++)
inline int read()
{
int x=;register char c=getc;
while(c<''||c>'')c=getc;
while(c>=''&&c<='')x=*x+(c^),c=getc;
return x;
}
int n,m,q;
struct edge{int st,ed,val,L,R;}s[M];
vector<edge>E;
struct Gragh
{
int fa[N];
inline int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
inline void intn(int sz){for(int i=;i<=sz;++i)fa[i]=i;}
}S;
inline bool mt(const edge &a,const edge &b){return a.val<b.val;}
LL ans[M];
int sta[M<<],stb[M<<],stc[M<<];
int id[N];
inline void CDQ(int l,int r,int size,vector<edge> Ex)
{
vector<edge> tmp;
int i,sz,x,y,cnt,mi=l+r>>;edge z;
for(i=,sz=Ex.size();i<sz;++i)
if(l<=Ex[i].R&&Ex[i].L<=r)tmp.push_back(Ex[i]);
sort(tmp.begin(),tmp.end(),mt);
S.intn(size);LL temp=;
for(i=,sz=tmp.size();i<sz;++i)
{
z=tmp[i],stc[i]=(z.L<=l&&r<=z.R),
sta[i]=stb[i]=,x=S.find(z.st),y=S.find(z.ed);
if(x!=y)
{
S.fa[x]=y;
if(stc[i])temp+=z.val,sta[i]=;
}
}
for(i=l;i<=r;++i)ans[i]+=temp;
if(l==r)return;
S.intn(size);
for(i=,sz=tmp.size();i<sz;++i)
{
z=tmp[i],x=S.find(z.st),y=S.find(z.ed);
if(x==y)stb[i]=;
else if(stc[i])S.fa[x]=y;
}
S.intn(size);
for(i=,sz=tmp.size();i<sz;++i)
if(sta[i]){z=tmp[i],S.fa[S.find(z.st)]=S.find(z.ed);}
for(cnt=,i=;i<=size;++i)
if(S.find(i)==i)id[i]=++cnt;
Ex.clear();
for(i=,sz=tmp.size();i<sz;++i)
if(!sta[i]&&!stb[i])
tmp[i].st=id[S.find(tmp[i].st)],
tmp[i].ed=id[S.find(tmp[i].ed)],
Ex.push_back(tmp[i]);
CDQ(l,mi,cnt,Ex);
CDQ(mi+,r,cnt,Ex);
}
int last[M];
int main()
{
register int i,j,x,y;edge z;
n=read(),m=read(),q=read();
for(i=;i<=m;++i)
s[i].st=read(),s[i].ed=read(),s[i].val=read();
for(i=;i<=q;++i)
x=read(),y=read(),z=s[x],z.L=last[x],z.R=i-,
E.push_back(z),s[x].val=y,last[x]=i;
for(i=;i<=m;++i)
s[i].L=last[i],s[i].R=q,E.push_back(s[i]);
CDQ(,q,n,E);
for(i=;i<=q;++i)
printf("%lld\n",ans[i]);
}

能AC的程序

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define inf 50000001
#define N 20010
#define M 50010
#define LL long long
char B[<<],*S=B,*T=B;
#define getc (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++)
inline int read()
{
int x=;register char c=getc;
while(c<''||c>'')c=getc;
while(c>=''&&c<='')x=*x+(c^),c=getc;
return x;
}
int n,m,q,top,sta[M],stb[M],topa;
int st[M],ed[M],val[M];
int changeid[M],changeval[M],mem[M];
inline bool mt(const int &a,const int &b){return val[a]<val[b];}
struct Gragh
{
int fa[N];int already;
vector<int>edge;
inline void operator = (const Gragh &b)
{memcpy(fa,b.fa,sizeof(fa)),edge=b.edge,already=b.already;}
inline int find(int a)
{return fa[a]==a?a:fa[a]=find(fa[a]);}
}G[];
LL ans[M];
inline void CDQ(int l,int r,int layer)
{
vector<int>::iterator it;
int i,sz,x,y,mi=l+r>>;
if(l==r)
{
val[changeid[l]]=changeval[l];
sort(G[layer].edge.begin(),G[layer].edge.end(),mt);
for(it=G[layer].edge.begin();G[layer].already<n-&&it!=G[layer].edge.end();++it)
{
x=G[layer].find(st[*it]),y=G[layer].find(ed[*it]);
if(x!=y)++G[layer].already,G[layer].fa[x]=y,ans[l]+=val[*it];
}
return;
}
for(int i=l;i<=r;++i)mem[changeid[i]]=val[changeid[i]];
for(int i=l;i<=r;++i)val[changeid[i]]=-inf;
sort(G[layer].edge.begin(),G[layer].edge.end(),mt);
LL temp=;sz=;topa=;
for(it=G[layer].edge.begin();sz!=n-&&G[layer].already!=n-&&it!=G[layer].edge.end();++it)
{
x=G[layer].find(st[*it]),y=G[layer].find(ed[*it]);
if(x!=y)
{
++sz,G[layer].fa[x]=y;
if(val[*it]!=-inf)sta[++topa]=*it,temp+=val[*it],++G[layer].already;
}
}
for(x=l;x<=r;++x)ans[x]+=temp;
G[layer]=G[layer-];
for(int i=l;i<=r;++i)val[changeid[i]]=inf;
sort(G[layer].edge.begin(),G[layer].edge.end(),mt);
memset(stb,,sizeof(stb));
for(sz=,it=G[layer].edge.begin();sz!=n-&&it!=G[layer].edge.end();++it)
{
x=G[layer].find(st[*it]),y=G[layer].find(ed[*it]);
if(x!=y)++sz,G[layer].fa[x]=y;
else if(val[*it]!=inf)stb[*it]=;
}
for(;it!=G[layer].edge.end();++it)
if(val[*it]!=inf)stb[*it]=;
G[layer]=G[layer-];
for(i=;i<=topa;++i)
x=G[layer].find(st[sta[i]]),y=G[layer].find(ed[sta[i]]),G[layer].fa[x]=y;
for(i=,sz=G[layer].edge.size();i<sz;++i)
if(stb[ G[layer].edge[i] ])
G[layer].edge[i]=G[layer].edge[sz-],--sz,--i,G[layer].edge.pop_back();
for(int i=l;i<=r;++i)val[changeid[i]]=mem[changeid[i]];
G[layer+]=G[layer],CDQ(l,mi,layer+);
G[layer+]=G[layer],CDQ(mi+,r,layer+);
}
int main()
{
register int i,j;n=read(),m=read(),q=read();
for(i=;i<=m;++i)
st[i]=read(),ed[i]=read(),val[i]=read(),
G[].edge.push_back(i),G[].edge.push_back(i);
for(i=;i<=n;++i)G[].fa[i]=G[].fa[i]=i;
G[].already=G[].already=;
for(i=;i<=q;++i)
changeid[i]=read(),changeval[i]=read();
CDQ(,q,);
for(i=;i<=q;++i)
printf("%lld\n",ans[i]);
}

TLE的程序

BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治的更多相关文章

  1. BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】

    题目链接 BZOJ2001 题解 CDQ分治神题... 难想难写.. 比较朴素的思想是对于每个询问都求一遍\(BST\),这样做显然会爆 考虑一下时间都浪费在了什么地方 我们每次求\(BST\)实际上 ...

  2. BZOJ2001: [Hnoi2010]City 城市建设

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2001 cdq分治+重建图. 可以保留当前一定会被选的非修改边然后把点缩起来.这样的话每次点数至 ...

  3. bzoj 2001 CITY 城市建设 cdq分治

    题目传送门 题解: 对整个修改的区间进行分治.对于当前修改区间来说,我们对整幅图中将要修改的边权都先改成-inf,跑一遍最小生成树,然后对于一条树边并且他的权值不为-inf,那么这条边一定就是树边了. ...

  4. 【BZOJ2001】 [Hnoi2010]City 城市建设

    BZOJ2001 [Hnoi2010]City 城市建设 Solution 我们考虑一下这个东西怎么求解? 思考无果...... 咦? 好像可以离线cdq,每一次判断一下如果这条边如果不选就直接删除, ...

  5. BZOJ 2001: [Hnoi2010]City 城市建设

    2001: [Hnoi2010]City 城市建设 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1132  Solved: 555[Submit][ ...

  6. 【bzoj2001】 Hnoi2010—City 城市建设

    http://www.lydsy.com/JudgeOnline/problem.php?id=2001 (题目链接) 题意 给出一张无向图,$m$组操作,每次修改一条边的权值,对于每次操作输出修改之 ...

  7. bzoj 2001: City 城市建设 cdq

    题目 PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁.Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费.Louis希望建造最少的道路使得国内所有 ...

  8. [HNOI2010]CITY 城市建设

    问题: 给一张图,支持边长度修改,求MST 题解: 自己想就想不到了.. 考虑cdq分治 1.首先求出一定有用的边 对于未处理的边,全部设为-INF,求一次MST,出现在MST上的边一定最终出现在后面 ...

  9. 2001: [Hnoi2010]City 城市建设 - BZOJ

    DescriptionPS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁.Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费.Louis希望建造最少的 ...

随机推荐

  1. 大数据入门第二十四天——SparkStreaming(一)入门与示例

    一.概述 1.什么是spark streaming Spark Streaming is an extension of the core Spark API that enables scalabl ...

  2. test temp

    http://img3.cache.netease.com/love/cssjs/20026/script/page/common.jshttp://img3.cache.netease.com/lo ...

  3. 20155227《网络对抗》Exp7 网络欺诈防范

    20155227<网络对抗>Exp7 网络欺诈防范 实践内容(3.5分) 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有 (1)简单应用SET工具建 ...

  4. 20155302《网络对抗》Exp8 Web基础

    20155302<网络对抗>Exp8 Web基础 实验内容 (1).Web前端HTML(0.5分) 能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个 ...

  5. 20155338课程设计个人报告——基于ARM实验箱的Android交友软件的设计与实现

    课程设计个人报告--基于ARM实验箱的Android交友软件的设计与实现 个人贡献 实验环境的搭建 代码调试 在电脑上成功运行 研究程序代码撰写小组报告 一.实验环境 1.Eclipse软件开发环境: ...

  6. JavaEE笔记(十四)

    #SSH配置文件整合笔记实例 spring-BaseBean.xml <?xml version="1.0" encoding="UTF-8"?> ...

  7. mfc 动态为控件添加事件1

    知识点: 认识窗口过程 GetWindowLong SetWindowLong 为动态控件绑定事件 一.获取窗口过程 二.设置新窗口过程 .书写一个新窗口过程函数 窗口过程格式 LRESULT CAL ...

  8. C语言学习之结构体

    前言 一直以来,C语言的学习都在入门阶段,只用到数组.函数.循环.选择.位运算这些基本的知识,较少用到指针.预处理.结构体.枚举类型.文件操作等这些C语言的精髓内容,现在想想真不敢说自己熟练掌握C语言 ...

  9. 微信小程序之缓存——不同页面传递数据

    1. 添加缓存 单个密钥允许存储的最大数据长度为1MB,所有数据存储上限为10MB. // 存储信息到storage // 异步存储 set() { wx.setStorage({ key: 'use ...

  10. Elasticsearch Query DSL 整理总结(一)—— Query DSL 概要,MatchAllQuery,全文查询简述

    目录 引言 概要 Query and filter context Match All Query 全文查询 Full text queries 小结 参考文档 引言 虽然之前做过 elasticse ...