[HNOI2010]城市建设

玄学cdq

O(nlog^2n)的动态最小生成树

其实就是按照时间cdq分治+剪枝(剪掉一定出现和不可能出现的边)

处理[l,r]之间的修改以及修改之后的询问,不能确定是否加入的边集为E

对于会被改变边权的边,边集为Q,暂时不能确定

不妨大力假设:

都是-inf,这个时候把Q的边都加入之后,剩下的E进行kruskal如果还能加入,那么在[l,r]这个区间里的所有询问,一定都能加进去

并查集带着必须边,然后处理Q都是inf,剩下的E进行kruskal,如果还是不能加入,那么在[l,r]这个区间里的所有询问,一定都不会加进去

这样,Q和第二次能加进去的边继续往左右递归,继续确定。

到了l==r时候,

把这个修改生效(因为之后再考虑的时候边权一定已经变了)

暴力把E中的边进行kruskal即可。

按秩合并并查集撤销,有些必须边出了[l,r]可能就被替换了。

说白了就是,cdq分治,强行维护备选边集+大力剪枝

感性理解一下复杂度:

看做n,m,q同阶

当Q中的边集最分散的时候,也就是形成一棵树,此时能确定的边是最少的。

这样,每次len/2,那么至少会多确定len/2个边(解放了n/2个点)

规模大概/=2

实际应该远不到上界,但是sort常数很大

O(nlog^2n)

注意,并查集不要随手写成路径压缩!!!

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{
const int N=+;
int n,m,q;
struct edge{
int x,y,w;
bool friend operator <(edge a,edge b){
return a.w<b.w;
}
}E[N];
bool cmp(int x,int y){
return E[x]<E[y];
}
struct qs{
int id,w;
}Q[N];
ll ans[N];
int fa[N],sz[N];
int exi[N],tag;
int fin(int x){return fa[x]==x?x:fin(fa[x]);}
vector<pair<int *,int> >buc;
void push(int &x,int v){buc.push_back(mk(&x,x));x=v;}
void roll(int t){
while((int)buc.size()>t) *buc.back().fi=buc.back().se,buc.pop_back();
}
void merge(int x,int y){
x=fin(x);y=fin(y);
if(x==y) return;
if(sz[x]>sz[y]) swap(x,y);
push(fa[x],y);push(sz[y],sz[x]+sz[y]);
}
void wrk(vector<int> &e,int l,int r,ll &val){
int st=buc.size();
static vector<int>tmp;tmp.clear();
sort(e.begin(),e.end(),cmp);
for(reg i=l;i<=r;++i) merge(E[Q[i].id].x,E[Q[i].id].y);
for(solid i:e){
if(exi[i]==tag) continue;
int x=fin(E[i].x),y=fin(E[i].y);
if(x!=y){
merge(x,y);val+=E[i].w;tmp.pb(i);
}
}
roll(st);
for(solid i:tmp){
merge(E[i].x,E[i].y);
}
}
void dele(vector<int> &e){
vector<int>tmp;
sort(e.begin(),e.end(),cmp);
int st=buc.size();
for(solid i:e){
if(exi[i]==tag){
tmp.pb(i);continue;
}
int x=fin(E[i].x),y=fin(E[i].y);
if(x!=y){
merge(x,y);tmp.pb(i);
}
}
roll(st);
e.swap(tmp);
}
void sol(int l,int r,vector<int>e,ll val){
// cout<<" l "<<l<<" r "<<r<<" val "<<val<<endl;
// for(solid i:e){
// cout<<i<<" ";
// }enter;
if(l==r) E[Q[l].id].w=Q[l].w;
int st=buc.size();
if(l==r){
sort(e.begin(),e.end(),cmp);
for(solid i:e){
int x=fin(E[i].x),y=fin(E[i].y);
if(x!=y){
merge(x,y);val+=E[i].w;
}
}
ans[l]=val;
}else{
++tag;
for(reg i=l;i<=r;++i) exi[Q[i].id]=tag;
wrk(e,l,r,val);
dele(e);
int mid=(l+r)>>;
sol(l,mid,e,val);sol(mid+,r,e,val);
}
roll(st);
}
int main(){
rd(n);rd(m);rd(q);
vector<int>st;
for(reg i=;i<=m;++i){
rd(E[i].x);rd(E[i].y);rd(E[i].w);
st.push_back(i);
}
for(reg i=;i<=n;++i) fa[i]=i,sz[i]=;
for(reg i=;i<=q;++i){
rd(Q[i].id);rd(Q[i].w);
}
sol(,q,st,);
for(reg i=;i<=q;++i){
printf("%lld\n",ans[i]);
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
*/

[HNOI2010]城市建设的更多相关文章

  1. 【BZOJ2001】[HNOI2010]城市建设(CDQ分治,线段树分治)

    [BZOJ2001][HNOI2010]城市建设(CDQ分治,线段树分治) 题面 BZOJ 洛谷 题解 好神仙啊这题.原来想做一直不会做(然而YCB神仙早就切了),今天来怒写一发. 很明显这个玩意换种 ...

  2. 【LG3206】[HNOI2010]城市建设

    [LG3206][HNOI2010]城市建设 题面 洛谷 题解 有一种又好想.码得又舒服的做法叫线段树分治+\(LCT\) 但是因为常数过大,无法跑过此题. 所以这里主要介绍另外一种玄学\(cdq\) ...

  3. BZOJ2001 HNOI2010 城市建设

    题目大意:动态最小生成树,可以离线,每次修改后回答,点数20000,边和修改都是50000. 顾昱洲是真的神:顾昱洲_浅谈一类分治算法 链接: https://pan.baidu.com/s/1c2l ...

  4. BZOJ2001 HNOI2010城市建设(线段树分治+LCT)

    一个很显然的思路是把边按时间段拆开线段树分治一下,用lct维护MST.理论上复杂度是O((M+Q)logNlogQ),实际常数爆炸T成狗.正解写不动了. #include<iostream> ...

  5. [HNOI2010] 城市建设_动态最小生成树(Dynamic_MST)

    这个题...暴力单次修改\(O(n)\),爆炸... $ $ 不过好在可以离线做 如果可以在 分治询问 的时候把图缩小的话就可以做了 硬着头皮把这个骚东西看完了 $ $ 动态最小生成树 然后,就把它当 ...

  6. 【CDQ分治】[HNOI2010]城市建设

    题目链接 线段树分治+LCT只有80 然后就有了CDQ分治的做法 把不可能在生成树里的扔到后面 把一定在生成树里的扔到并查集里存起来 分治到l=r,修改边权,跑个kruskal就行了 由于要支持撤销, ...

  7. Luogu 3206 [HNOI2010]城市建设

    BZOJ 2001 很神仙的cdq分治 先放论文的链接   顾昱洲_浅谈一类分治算法 我们考虑分治询问,用$solve(l, r)$表示询问编号在$[l, r]$时的情况,那么当$l == r$的时候 ...

  8. 洛谷P3206 [HNOI2010]城市建设

    神仙题 题目大意: 有一张\(n\)个点\(m\)条边的无向联通图,每次修改一条边的边权,问每次修改之后这张图的最小生成树权值和 话说是不是\(cdq\)题目都可以用什么数据结构莽过去啊-- 这道题目 ...

  9. P3206 [HNOI2010]城市建设 [线段树分治+LCT维护动态MST]

    Problem 这题呢 就边权会在某一时刻变掉-众所周知LCT不支持删边的qwq- 所以考虑线段树分治- 直接码一发 如果 R+1 这个时间修改 那就当做 [L,R] 插入了一条边- 然后删的边和加的 ...

随机推荐

  1. 禁用了传说中的PHP危险函数之后,Laravel的定时任务不能执行了?

    虽然已是 2018 年,但网上依然流传着一些「高危 PHP 函数,请一定要禁用!」的标题党文章(搜索关键字:一些需要禁用的PHP危险函数). 这些文章的内容简单直接,给出 php.ini 的 disa ...

  2. webpack中使用DefinePlugin定义全局变量

    DefinePlugin可以在编译时期创建全局变量.DefinePlugin是webpack注入全局变量的插件,通常使用该插件来判别代码运行的环境变量.

  3. 第二次上机,ASP内置对象的使用

    3.新建Reg.asp文档,参照1中的Reg.html,通过VBScript服务器端脚本代码实现 ”班级” Select表单的自动生成,如下所示: 注:通过循环语句,采用Response.Write命 ...

  4. MyBatis学习---整合SpringMVC

    [目录]

  5. Mac10.12下Python3.4调用oracle

    最近,由于项目的短信平台对其它浏览器兼容,只支持IE,但是我们移动端自动化需要测试iphone手机,必须要连接MAC系统下,众所周知,MAC对IE的不友好性,故没办法通过短信平台在UI层自动化获取短信 ...

  6. Flink应用案例:How Trackunit leverages Flink to process real-time data from industrial IoT devices

    January 22, 2019Use Cases, Apache Flink Lasse Nedergaard     Recently there has been significant dis ...

  7. ubuntu18.04安装spark(伪分布式)

    在安装spark之前,首先需要安装配置Hadoop,这个就不做详细介绍了,可以参看博主的另一篇: https://blog.csdn.net/weixin_42001089/article/detai ...

  8. JProfiler的详细使用介绍

    转:https://blog.csdn.net/huangjin0507/article/details/52452946 下载软件 官网地址:http://www.ej-technologies.c ...

  9. redis对sorted_set进行的相关操作

    redis对sorted_set(有序集合)类型操作的相关命令以及如何在python使用这些命令 redis对sorted_set(有序集合)类型操作的命令: 命令 语法 概述 返回值 Redis Z ...

  10. UltraEdit文本行数多变一和一边多

    一.UltraEdit文本行数多行转换成一行 1.文本样式内容 1.qwertyuuiopqwertyuuiopqwertyuuiopqwertyuuiopqwertyuuiopqwertyuuiop ...