luogu5193 炸弹 (扫描线)

就是求连通块的数量,可以维护一个斜着的扫描线,set里只保留在R范围内的点

然而怎么维护连通块呢。。

其实只需要向能够到的最靠左和最靠右的点连边就可以,剩下的点之前就已经连好了

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 #define MP make_pair
 5 #define fi first
 6 #define se second
 7 using namespace std;
 8 typedef long long ll;
 9 typedef unsigned long long ull;
10 typedef unsigned int ui;
11 typedef long double ld;
12 const int maxn=1e5+10;
13 
14 inline char gc(){
15     return getchar();
16     static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf;
17     return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
18 }
19 inline ll rd(){
20     ll x=0;char c=gc();bool neg=0;
21     while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();}
22     while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc();
23     return neg?(~x+1):x;
24 }
25 
26 struct Node{
27     int x,y;
28 }p[maxn];
29 int N,R,fa[maxn];
30 set<pa> st;
31 bool flag[maxn];
32 
33 inline bool cmp(Node a,Node b){return a.y-a.x>b.y-b.x;}
34 
35 inline int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}
36 
37 inline void uni(int x,int y){
38     x=getf(x),y=getf(y);
39     if(x!=y) fa[x]=y;
40 }
41 
42 int main(){
43     //freopen("","r",stdin);
44     N=rd();R=rd();
45     for(int i=1;i<=N;i++) p[i].x=rd(),p[i].y=rd();
46     for(int i=1;i<=N;i++) fa[i]=i;
47     sort(p+1,p+N+1,cmp);
48     for(int i=1,j=1;i<=N;i++){
49         for(;j<i&&(p[j].y-p[j].x)-(p[i].y-p[i].x)>R;j++) st.erase(MP(p[j].x+p[j].y,j));
50         if(i>1){
51             set<pa>::iterator it=st.lower_bound(MP(p[i].x+p[i].y-R,0));
52             if(it!=st.end()&&it->fi<=p[i].x+p[i].y+R) uni(it->se,i);
53             it=st.upper_bound(MP(p[i].x+p[i].y+R,N));
54             if(it!=st.begin()){
55                 --it;
56                 if(it->fi>=p[i].x+p[i].y-R) uni(it->se,i);
57             }
58         }
59         
60         st.insert(MP(p[i].x+p[i].y,i));
61     }
62     int ans=0;
63     for(int i=1;i<=N;i++){
64         if(!flag[getf(i)]) ans++; 
65         flag[getf(i)]=1;
66     }
67     printf("%d\n",ans);
68     return 0;
69 }

 

posted @ 2019-05-02 17:29  Ressed  阅读(253)  评论(0编辑  收藏  举报