牛客8 E Explorer 线段树分治
作者:互联网
题意: n 个点 m 条双向边 每条双向边有一个上界 和一个下界 当 尺寸 下界<=(size)<=上界 时才可以通过 问有多少种尺寸可以从1 到n
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) typedef pair<int,int>pii; ////////////////////////////////// const int N=1e5+10; vector<int>t[800000+10]; int l[N],r[N],b[2*N],u[N],v[N],n,m,nn; #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 void upsum(int L,int R,int id,int l,int r,int pos) { if(L<=l&&r<=R) return (void)t[pos].push_back(id); int m=(l+r)>>1; if(L<=m)upsum(L,R,id,lson); if(R>m)upsum(L,R,id,rson); } int ans,f[N],x,y,siz[N]; int find1(int x) { return f[x]==x?x:find1(f[x]); } void dfs(int l,int r,int pos) { vector<int>lastf; int m=(l+r)>>1; for(auto i:t[pos]) { int x=find1(u[i]),y=find1(v[i]); if(x==y)continue; if(siz[x]>siz[y])swap(x,y); f[x]=y;lastf.push_back(x); siz[y]+=siz[x]; } if(find1(1)==find1(n))ans+=b[r+1]-b[l]; else if(l<r)dfs(lson),dfs(rson); for(auto i:lastf)f[i]=i; lastf.clear(); } int main() { scanf("%d%d",&n,&m); rep(i,1,n)f[i]=i,siz[i]=1; rep(i,1,m) { scanf("%d%d%d%d",&u[i],&v[i],&l[i],&r[i]); r[i]++;b[++nn]=l[i];b[++nn]=r[i]; } sort(b+1,b+1+nn); nn=unique(b+1,b+1+nn)-b-1; rep(i,1,m)upsum(lower_bound(b+1,b+1+nn,l[i])-b,lower_bound(b+1,b+1+nn,r[i])-b-1,i,1,nn-1,1); dfs(1,nn-1,1); printf("%d\n",ans); return 0; }View Code
注意size 改成左闭右开
标签:Explorer,int,siz,线段,pos,牛客,ans,define,find1 来源: https://www.cnblogs.com/bxd123/p/11335569.html