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. 关于OpenCV2.4.9在VS2012上的配置

    今天写着篇文章是由于自从上次电脑换硬盘今天再次安装OpenCV又遇到了一些问题,最后终于搞定,,,,用的版本是2.4.9,,,因为第一次配置用3.0的没有配置成功,而2.4.9的配置成功. 首先当然是 ...

  2. Centos7 安装ELK日志分析

    1.安装前准备 借鉴:https://www.cnblogs.com/straycats/p/8053937.html 操作系统:Centos7 虚拟机  8G内存  jdk8+ 软件包下载:采用rp ...

  3. iscsi target tgt架构

    tgt是用户态实现的iscsi target,而iet(iscsi enterprise target)是在内核态实现的target,tgt相比于iet来说,因为其用户态实现,方便调试,新加入一些功能 ...

  4. 20155234 Exp3 免杀原理与实践

    使用msf编码器生成jar包 使用指令:msfvenom -p java/meterpreter/reverse_tcp lhost=192.168.157.141 lport=5234 x> ...

  5. Python基础(字符串和编码)

    字符编码 我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特 ...

  6. 浅析arm的异常、中断和arm工作模式的联系

    说到异常向量,会让人联想到中断向量.其实,中断是属于异常的子集的,也就是说中断其实是异常其中的一种. 回到异常向量,他其实是一张表格,每个格子里存放的是一个地址,或者是一个跳转命令,不管是哪个,其目的 ...

  7. 【LG4070】[SDOI2016]生成魔咒

    [LG4070][SDOI2016]生成魔咒 题面 洛谷 题解 如果我们不用在线输的话,那么答案就是对于所有状态\(i\) \[ \sum (i.len-i.fa.len) \] 现在我们需要在线询问 ...

  8. 双面间谍(spy)

    双面间谍 链接 分析: 戳这 代码: #include<cstdio> #include<algorithm> #include<cstdio> #include& ...

  9. Redis学习之路(三)之Redis主从和哨兵模式

    目录 一.Redis主从配置 1.环境说明 2.修改主从的redis配置文件 3.启动主从redis 3.数据同步验证 二.Redis哨兵模式 1.Redis sentinel介绍 2.Redis S ...

  10. ubuntu下安装搜狗输入法

    1.如果系统中未安装依赖fcitx,libssh2-1,或者依赖fcitx,libssh2-1的版本低的话,则需提前安装或者升级,否则安装输入法时会出错 安装命令 sudo apt-get insta ...