【CF471E】MUH and Lots and Lots of Segments 扫描线+并查集+线段树+set
2018-04-01 09:25
369 查看
【CF471E】MUH and Lots and Lots of Segments
题意:给你平面上n条水平或竖直的,端点在整点处的线段。你需要去掉一些线段的一些部分,使得剩下的图形:1.连通,2.无环,3.端点依旧位于整点处。$n\le 2\times 10^5$
题解:如果把整点看成点的话,那么这题让你求的就是一棵生成树。一棵生成树的边数就是这个连通块内点数-1,所以我们找到最大的连通块将其点数-1就是答案。
具体实现中,我们先进行扫描线,用并查集维护连通性,用线段树快速查找区间中点的数量以及一个点的前驱后继,用set维护所有所在连通块与后继所在连通块不同的点即可。
不知道为什么思考的过程中想到了Kruskal。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <set> #define lson x<<1 #define rson x<<1|1 using namespace std; const int maxn=200010; typedef long long ll; int n,m,np,nq; int f[maxn<<1],org[maxn<<1]; ll ans; ll ref[maxn<<1]; struct edge { int l,r,x; }p[maxn],q[maxn<<1]; ll s[maxn<<3],sum[maxn<<1]; set<int> st; set<int>::iterator it; bool cmp(const edge &a,const edge &b) { return (a.x==b.x)?(a.r>b.r):(a.x<b.x); } int find(int x) { return (f[x]==x)?x:(f[x]=find(f[x])); } void updata(int l,int r,int x,int a,int b) { s[x]+=b; if(l==r) return ; int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a,b); else updata(mid+1,r,rson,a,b); } int count(int l,int r,int x,int a,int b) { if(a>b) return 0; if(a<=l&&r<=b) return s[x]; int mid=(l+r)>>1; if(b<=mid) return count(l,mid,lson,a,b); if(a>mid) return count(mid+1,r,rson,a,b); return count(l,mid,lson,a,b)+count(mid+1,r,rson,a,b); } int find(int l,int r,int x,int a) { if(l==r) return l; int mid=(l+r)>>1; if(a<=s[lson]) return find(l,mid,lson,a); return find(mid+1,r,rson,a-s[lson]); } inline int pre(int x) { int t=count(1,m,1,1,x); if(t==1) return -1; return find(1,m,1,t-1); } inline int nxt(int x) { int t=count(1,m,1,1,x); if(t==s[1]) return -1; return find(1,m,1,t+1); } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar(); return ret*f; } int main() { n=rd(); int i,j,a,b,c,d; ll tmp; for(i=1;i<=n;i++) { a=rd(),b=rd(),c=rd(),d=rd(); if(b==d) { q[++nq].x=a,q[nq].l=b,q[nq].r=c-a+1; q[++nq].x=c,q[nq].l=b,q[nq].r=0; ref[++m]=b; } else { p[++np].x=a,p[np].l=b,p[np].r=d; ref[++m]=b,ref[++m]=d; ans=max(ans,ll(d-b)); } } sort(ref+1,ref+m+1); for(i=1,j=0,ref[0]=-1<<30;i<=m;i++) if(ref[i]!=ref[j]) ref[++j]=ref[i]; m=j; for(i=1;i<=nq;i++) q[i].l=lower_bound(ref+1,ref+m+1,q[i].l)-ref,f[i]=i; for(i=1;i<=np;i++) p[i].l=lower_bound(ref+1,ref+m+1,p[i].l)-ref,p[i].r=lower_bound(ref+1,ref+m+1,p[i].r)-ref; sort(p+1,p+np+1,cmp); sort(q+1,q+nq+1,cmp); for(i=j=1;i<=np;i++) { while(j<=nq&&(q[j].x<p[i].x||(q[j].x==p[i].x&&q[j].r))) { a=q[j].l,b=q[j].r; if(b) { org[a]=j,sum[j]=b; st.insert(a); updata(1,m,1,a,1); c=pre(a); if(c!=-1) st.insert(c); } else { it=st.find(a); if(it!=st.end()) st.erase(it); c=pre(a); if(c!=-1) st.insert(c); updata(1,m,1,a,-1); } j++; } tmp=ref[p[i].r]-ref[p[i].l]+1-count(1,m,1,p[i].l,p[i].r); a=p[i].l-1,c=nxt(a); if(c<=p[i].r) { sum[find(org[c])]+=tmp; while(1) { it=st.lower_bound(p[i].l); if(it==st.end()||(*it)>p[i].r) break; a=*it,c=nxt(a); if(c==-1||c>p[i].r) break; st.erase(it); b=find(org[a]),d=find(org[c]); if(b!=d) sum[d]+=sum[b],f[b]=d; } } } for(i=1;i<=nq;i++) ans=max(ans,sum[i]-1); printf("%lld",ans); return 0; }
相关文章推荐
- Structure of a C-Program in Memory | How Heap,Stack,Data and Code segments are stored in memory?
- codeforces 471C MUH and House of Cards 数论
- C. MUH and House of Cards(数论规律题)
- CF&&CC百套计划2 CodeChef December Challenge 2017 Chef and Hamming Distance of arrays
- CF 305C ——Ivan and Powers of Two——————【数学】
- Codeforces Round #337 (Div. 2) D. Vika and Segments (线段树+扫描线+离散化)
- CodeForces 471C - MUH and House of Cards(推导)
- Codeforces 471C MUH and House of Cards【找规律+二分】
- 扫描线算法的论文《The Intersections for a Set of 2D Segments, and Testing Simple Polygons》的部分翻译
- CF 489 C Given Length and Sum of Digits...(水题)
- CF#The Union of k-Segments -离散化+树状数组
- Gradient Panel With Shadow Support And Lots Of Other Stuff
- CF_850B Arpa and a list of numbers
- MUH and House of Card
- CF 439C(251C题)Devu and Partitioning of the Array
- (CF)B. Inna and New Matrix of Candies
- CF_305_C. Ivan and Powers of Two
- Codeforces 610D Vika and Segments 线段树+离散化+扫描线
- Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树扫描线
- CF_305_C. Ivan and Powers of Two