BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治
2017-12-12 16:30
302 查看
2001: [Hnoi2010]City 城市建设
Time Limit: 20 Sec Memory Limit: 162 MBDescription
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 31 2 1
2 3 2
3 4 3
4 5 4
5 1 5
1 6
1 1
5 3
Sample Output
1410
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[1<<15],*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=0;register char c=getc; while(c<'0'||c>'9')c=getc; while(c>='0'&&c<='9')x=10*x+(c^48),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 ;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[20]; LL ans[M]; inline void CDQ(int l,int r,int layer) { vector<int>::iterator it; int i,sz,x,y,mi=l+r>>1; 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-1&&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=0;sz=0;topa=0; for(it=G[layer].edge.begin();sz!=n-1&&G[layer].already!=n-1&&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-1]; for(int i=l;i<=r;++i)val[changeid[i]]=inf; sort(G[layer].edge.begin(),G[layer].edge.end(),mt); memset(stb,0,sizeof(stb)); for(sz=0,it=G[layer].edge.begin();sz!=n-1&&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]=1; } for(;it!=G[layer].edge.end();++it) if(val[*it]!=inf)stb[*it]=1; G[layer]=G[layer-1]; for(i=1;i<=topa;++i) x=G[layer].find(st[sta[i]]),y=G[layer].find(ed[sta[i]]),G[layer].fa[x]=y; for(i=0,sz=G[layer].edge.size();i<sz;++i) if(stb[ G[layer].edge[i] ]) G[layer].edge[i]=G[layer].edge[sz-1],--sz,--i,G[layer].edge.pop_back(); for(int i=l;i<=r;++i)val[changeid[i]]=mem[changeid[i]]; G[layer+1]=G[layer],CDQ(l,mi,layer+1); G[layer+1]=G[layer],CDQ(mi+1,r,layer+1); } int main() { register int i,j;n=read(),m=read(),q=read(); for(i=1;i<=m;++i) st[i]=read(),ed[i]=read(),val[i]=read(), G[0].edge.push_back(i),G[1].edge.push_back(i); for(i=1;i<=n;++i)G[0].fa[i]=G[1].fa[i]=i; G[0].already=G[1].already=0; for(i=1;i<=q;++i) changeid[i]=read(),changeval[i]=read(); CDQ(1,q,1); for(i=1;i<=q;++i) printf("%lld\n",ans[i]); }
TLE的程序
相关文章推荐
- BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】
- [动态最小生成树 CDQ分治 Kruscal] BZOJ 2001 [Hnoi2010]City 城市建设
- 【BZOJ】2001 [Hnoi2010]City 城市建设 cdq分治——动态最小生成树
- [动态MST] [CDQ分治] BZOJ2001: [Hnoi2010]City 城市建设
- [bzoj2001][Hnoi2010][City 城市建设] (cdq分治)
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- [BZOJ2001][HNOI2010]City城市建设-CDQ分治
- BZOJ 2001 [Hnoi2010]City 城市建设 LCT+分治(未成功卡时卡过)
- BZOJ 2001([Hnoi2010]City 城市建设-CDQ重构图-动态最小生成树)
- bzoj2001 [Hnoi2010]City 城市建设
- bzoj2001【HNOI2010】City 城市建设
- 【BZOJ2001】[Hnoi2010]City 城市建设
- [BZOJ2001][Hnoi2010]City 城市建设(CDQ分治+并查集)
- bzoj 2001 [Hnoi2010]City 城市建设
- bzoj2001 [Hnoi2010]City 城市建设 动态最小生成树
- bzoj 2001: [Hnoi2010]City 城市建设
- bzoj2001 [Hnoi2010]City 城市建设
- BZOJ 2001 Hnoi2010 城市建设 分治+LCT
- 【bzoj2001】[Hnoi2010]City 城市建设
- bzoj2001: [Hnoi2010]City 城市建设 wikioi2332