[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. Spring Tool Suite4(sts)复制粘贴卡顿(ctrl+v, ctrl+c)、按住ctrl也很卡

    最近在看<Spring in Action, Fifth Edition>,下载了Spring Tool Suite4,在使用的过程中发现了一些问题: 只要在复制粘贴(ctrl+c, ct ...

  2. 从APP跳转到微信指定联系人聊天页面功能的实现与采坑之旅

    起因: 最近做的APP中有一个新功能:已知用户微信号,可点击直接跳转到当前用户微信聊天窗口页面. 当时第一想法是使用无障碍来做,并且觉得应该不难,只是逻辑有点复杂.没想到最终踩了好多坑,特地把踩过的坑 ...

  3. Android ble蓝牙使用注意

    以下均为自己在Android ble开发项目中遇到的问题 1.尽量不要在BluetoothGattCallback里面的回调函数中执行读写通知操作,最多一个,因为例如在onServicesDiscov ...

  4. Android视频录制从不入门到入门系列教程(四)————Camera Parameter

    Camera提供了一个叫做setParameters的方法帮助开发者设置相机的相关参数. 通过Camera的getParameters方法可以获取到当前为相机设置的相关参数. 下面简单介绍下,视频录制 ...

  5. 搭建Linux虚拟服务器

    1.搭建Linux虚拟机环境安装VMware Workstation 14下载地址:https://www.cr173.com/soft/68480.html密钥:FF31K-AHZD1-H8ETZ- ...

  6. rocketmq延时消息

    rocketmq提供一种延时消息的解决方案,就是在特定的时间到了,消息才会被投递出去供consumer消费. 总体来是简单的场景是满足了,但是需要注意的是延时的时间是需要按照默认配置的延时级别去配置的 ...

  7. mysql No query specified

    MySQL SHOW CREATE TABLE tablename \G; 会出现 ERROR: No query specified 原因 去掉分号 ; \g \G三者选其一即可.

  8. LeetCode算法题-Shortest Completing Word(Java实现)

    这是悦乐书的第309次更新,第330篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第178题(顺位题号是748).从给定的字典单词中查找最小长度单词,其中包含字符串lic ...

  9. 【心得】Lattice后端使用经验小结(ECP5UM,DDR3,Diamond3.10,Reveal逻辑分析)

    [博客导航] [导航]FPGA相关 背景 下边的内容,适合初次使用Lattice的.具备FPGA开发经验的同学. 1.初次使用,还真遇到不少的坑,Lattice的工具也有不少优缺点,通过总结,希望能缩 ...

  10. 工作中遇到的一些linux常用命令总结

    零.查看历史命令,linux中可按“↑” “↓”查找之前输入的命令,亦可用 history 命令查看之前的输入,linux中的亦有“Tab”键可联想输入 一.root权限: 1.su 之后输入root ...