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. 关于C#中async/await中的异常处理(上)-(转载)

    在同步编程中,一旦出现错误就会抛出异常,我们可以使用try…catch来捕捉异常,而未被捕获的异常则会不断向上传递,形成一个简单而统一的错误处理机制.不过对于异步编程来说,异常处理一直是件麻烦的事情, ...

  2. 20155217《网络对抗》Exp01 PC平台逆向破解(5)M

    20155217<网络对抗>Exp01 PC平台逆向破解(5)M 实验要求 掌握NOP,JNE,JE,JMP,CMP汇编指令的机器码 掌握反汇编与十六进制编程器 能正确修改机器指令改变程序 ...

  3. 20155223 Exp2 后门原理与实践

    20155223 Exp2 后门原理与实践 实验预热 一.windows获取Linux shell Windows:使用 ipconfig 命令查看当前机器IP地址. 进入ncat所在文件地址,输入命 ...

  4. WPF编程,通过Path类型制作沿路径运动的动画一种方法。

    原文:WPF编程,通过Path类型制作沿路径运动的动画一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/de ...

  5. Python的进制等转换

    To 十进制 二进制: >>> int('110', 2) -> 6 八进制: >>> int('10', 8) -> 8 十六进制: >> ...

  6. flask前端与后端之间传递的两种数据格式:json与FormData

    json格式 双向! 前端 ==>后端:json格式 后端 ==>前端:json格式 html <!-- html部分 --> <form enctype='applic ...

  7. libgdx学习记录25——Rectangle与Circle是否重叠

    Rect与Circle重叠有三种情况: 1. Rect至少有一个角在Circle里面 2. Circle与Rect的左边或右边相交,或者Circle在Rect内 3. Circle与Rect的顶边或底 ...

  8. 内存和CPU资源控制

    数据库系统的资源是指内存和CPU(处理器)资源,拥有资源的多寡,决定了数据查询的性能.当一个SQL Server实例上,拥有多个独立的工作负载(workload)时,使用资源管理器(Resource ...

  9. .Net Core WebApi控制器接收原始请求正文内容

    主要目标 在Asp.net Core控制器中,通过自定义格式化程序来映射自定义处理控制器中的“未知”内容. 简单案例 为了演示这个问题,我们用VS2017创建一个默认的Asp.net Core Web ...

  10. 【Unity Shader】从NDC(归一化的设备坐标)坐标转换到世界坐标的数学原理

    从NDC(归一化的设备坐标)坐标转换到世界坐标要点 参考资料 How to go from device coordinates back to worldspace http://feepingcr ...