模板题。。去网上学了可撤销的并查集。。

/*
给定一个无向图,边的属性为(u,v,l,r),表示<u,v>可以通过的size为[l,r]
求出有多少不同的size可以从1->n
把每条边的范围[l,r]进行区间离散化然后 建立线段树,然后把每条边按范围更新进线段树里
对线段树进行dfs,同时维护一个可撤销的并查集,经过每个线段树结点都用结点里存的边去更新并查集
到了叶子结点,如果发现[1,n]在同一个集合里,说明联通,那么把这个区间的贡献算上
回溯时要对并查集进行撤销
*/
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 200005
typedef pair<int,int>pii;
struct Edge{int u,v,l,r;}e[maxn];
int n,m,x[maxn],tot,ans; stack<pii>stk;//合并操作栈
int F[maxn],size[maxn];
int find(int x){//这里不能路径压缩
return F[x]==x?x:find(F[x]);
}
void bing(int x,int y){
int f1=find(x),f2=find(y);
if(f1==f2)//压入无效操作
stk.push(make_pair(-,-));
else {//把f2并入f1
if(size[f1]<size[f2])swap(f1,f2);
size[f1]+=size[f2];
F[f2]=f1;
stk.push(make_pair(f1,f2));
}
}
void cancle(){
pii t=stk.top();stk.pop();
if(t.first==- && t.second==-)return;
size[t.first]-=size[t.second];
F[t.second]=t.second;
return;
} #define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
vector<int>seg[maxn<<];
void update(int L,int R,int id,int l,int r,int rt){
if(L<=l && R>=r){seg[rt].push_back(id);return;}
int m=l+r>>;
if(L<=m)update(L,R,id,lson);
if(R>m)update(L,R,id,rson);
}
void query(int l,int r,int rt){
for(int i=;i<seg[rt].size();i++){
int j=seg[rt][i];
bing(e[j].u,e[j].v);
}
if(l==r){
if(find()==find(n))
ans+=x[l+]-x[l];
for(int i=;i<seg[rt].size();i++)cancle();
return;
}
int m=l+r>>;
query(lson);query(rson);
for(int i=;i<seg[rt].size();i++)cancle();
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].l,&e[i].r);
for(int i=;i<=m;i++){
x[++tot]=e[i].l;
x[++tot]=++e[i].r;
}
sort(x+,x++tot);
tot=unique(x+,x++tot)-x-; for(int i=;i<=m;i++){
int posl=lower_bound(x+,x++tot,e[i].l)-x;
int posr=lower_bound(x+,x++tot,e[i].r)-x;posr--;
update(posl,posr,i,,tot,);
} for(int i=;i<=n;i++)F[i]=i;
for(int i=;i<=n;i++)size[i]=;
query(,tot,);
cout<<ans<<'\n';
}

下面是比较简洁的代码

#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 400005
typedef pair<int,int>pii; int n,m,x[maxn],tot;
long long ans;
int u[maxn],v[maxn],L[maxn],R[maxn],num[maxn]; stack<pii>stk;//合并操作栈
int fa[maxn],sz[maxn];
int find(int x){//这里不能路径压缩
return fa[x]==x?x:find(fa[x]);
}
void bing(int x,int y){
int f1=find(x),f2=find(y);
if(f1==f2)//压入无效操作
stk.push(make_pair(-,-));
else {//把f2并入f1
if(sz[f1]<sz[f2])swap(f1,f2);
sz[f1]+=sz[f2];
fa[f2]=f1;
stk.push(make_pair(f1,f2));
}
}
void cancel(){
pii t=stk.top();stk.pop();
if(t.first==- && t.second==-)return;
sz[t.first]-=sz[t.second];
fa[t.second]=t.second;
} #define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
vector<int>seg[maxn<<];
void update(int L,int R,int id,int l,int r,int rt){
if(L<=l && R>=r){seg[rt].push_back(id);return;}
int m=l+r>>;
if(L<=m)update(L,R,id,lson);
if(R>m)update(L,R,id,rson);
}
void query(int l,int r,int rt){
for(int i=;i<seg[rt].size();i++){
int j=seg[rt][i];
bing(u[j],v[j]);
}
if(l==r){
if(find()==find(n))
ans+=num[l+]-num[l];
for(int i=;i<seg[rt].size();i++)cancel();
return;
}
int m=l+r>>;
query(lson);query(rson);
for(int i=;i<seg[rt].size();i++)cancel();
}
int main(){
cin>>n>>m;
for(int i=;i<=m;i++){
cin>>u[i]>>v[i]>>L[i]>>R[i];
num[++tot]=L[i];
num[++tot]=++R[i];
}
sort(num+,num++tot);
tot=unique(num+,num++tot)-num-; for(int i=;i<=m;i++){
int posl=lower_bound(num+,num++tot,L[i])-num;
int posr=lower_bound(num+,num++tot,R[i])-num-;
update(posl,posr,i,,tot-,);
}
for(int i=;i<=n;i++)fa[i]=i,sz[i]=;
query(,tot-,);
cout<<ans<<endl;
}

最新文章

  1. nginx.conf
  2. AngularJS 实现简单购物车
  3. 弹窗插件layer
  4. 非在线方式搭建Android开发环境
  5. gearman安装及初次使用
  6. js设计模式(9)---代理模式
  7. pyqt信号事件相关网址说明及python相关
  8. iOS RTMP 视频直播开发笔记(1) – 采集摄像头图像
  9. MySQL性能、监控与灾难恢复
  10. 牛客网linux试题-错误整理-20171013
  11. 常用API接口签名验证参考
  12. tomcat配置文件及性能优化
  13. 你不知道的JS之作用域和闭包(五)作用域闭包
  14. 【转】Powershell与jenkins集成部署的运用(powershell运用)
  15. 阿里云 ECS centos java timer进程异常/混乱......的解决方法
  16. 再次回归 Spark-- 转
  17. 《Visual C# 从零开始学》
  18. 【转载】Etcd+Confd实现Nginx配置文件自动管理
  19. Git将本地项目上传到GitHub
  20. SQL左外连接

热门文章

  1. HIVE常用函数(1)聚合函数和序列函数
  2. elementUI表单嵌套时间报错
  3. python网络爬虫学习
  4. TotoiseSVN + VisualSVN Server 使用
  5. docker仓库管理(9)
  6. 51nod 1437 迈克步——单调栈
  7. __iomem作用
  8. python random生成随机手机号
  9. js读取json数据
  10. Django框架(四)—— 路由控制:有名/无名分组、反向解析、路由分发、名称空间、伪静态、APPEND_SLASH、不同版本的Django区别