[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. SpringMVC之入门程序

    SpringMVC之入门程序——使用浏览器展示商品数据 springMVC执行流程(图片来源:https://www.jianshu.com/p/8a20c547e245) 1.创建pojo(商品实体 ...

  2. Nginx配置了解

    安装Nginx常用编译选项说明 nginx大部分常用模块,编译时./configure --help查看,以--without开头的都是默认安装. --prefix=PATH 指定nginx的安装目录 ...

  3. Markdown 7min快速入门

    目录 概述 宗旨 兼容 特殊字符自动换行 区块元素 段落和换行 标题 区块引用 列表 代码区块 分隔线 区段元素 链接 强调 代码 图片 其他 表格 删除线 注脚 锚点 反斜杠 自动链接 参考文献 正 ...

  4. 使用Android服务,实现报警管理器和广播接收器

    介绍 几乎在所有平台上都有很多进程运行背景,它们被称为服务.可能在Android平台中有一些服务可以执行长时间运行的操作,这些操作在处理时不需要用户交互. 在本文中,借助预定义的Android警报服务 ...

  5. SpringBoot+MyBatis配置多数据源

    SpringBoot 可以支持多数据源,这是一个非常值得学习的功能,但是从现在主流的微服务的架构模式中,每个应用都具有唯一且准确的功能,多数据源的需求很难用到,考虑到实际情况远远比理论复杂的多,这里还 ...

  6. 服务器部署Apache+PHP+MYSQL+Laravel

    1.安装PHP 添加php安装源: sudo apt-get install python-software-properties sudo add-apt-repository ppa:ondrej ...

  7. 利用Navicat高效率postgresql转mysql数据库

    本人很喜欢postgresql数据库,也一直认为postgresql比mysql要更好更强大. 可生态环境太差了,无奈,最近要把一个小站转成mysql数据库. 小站主要表数据110万,pg_dump备 ...

  8. [已解决]报错:Required request body is missing

    问题代码: res = requests.post(getXxxxList_url, headers=headers, data={}) 对象网站: angular4 apache 通过验证 (coo ...

  9. python学习——读取染色体长度(一、简化问题)

    # 读取fasta # 解析每条序列的长度 chr1_len = 10 chr2_len = 20 chr3_len = 30 chr4_len = 40 chr5_len = 50 # 求和 tot ...

  10. Linux新增和删除环境变量

    vi ~/.bashrc 添加 export 变量名=值 使环境变量生效 source ~/.bashrc