cf1140f Extending Set of Points

题目链接

题目大意:每次给你一个点,如果这个点已经存在, 那么就删除这个点,如果这个点不存在,那么就加入这个点。每次询问当前集合的扩展集合中点的个数。

扩展集合是这么得到的,如果当前集合中存在矩形的3个点,那么第4个点就会被放到扩展集合中,不断这样拓展。 

 

思路: 首先我们要建图,横坐标相同的点连一条边,纵坐标相同的点连一条边,这样就组成了若干个联通块。我们统计每一个联通块里面不同的横坐标数量和纵坐标数量。他们数量的乘就是最终这个联通里面点的数量。  我们可以用并查集来维护这个过程。

注意这里要列点以后才能用并查集,把每个点看成是一条边,列成2个点,每个y+300000,然后建图,并查集统计的时候要统计x个数和y个数。  

由于这题还有删除操作,而并查是不支持删除操作的,所以我们要考虑每个点有效的一个时间范围,比如(1,2)在第1个询问到第8个询问有效,那么就把(1,2)插入到1-8这个区间,用线段树维护,这样每个区间最多会产生,$log(q)$次修改。 

然后我们dfs去遍历每个点,每到一个点,就把这个点(区间)对应的点全部放到并查及里面,当退出这个递归的时候,要恢复并查及,所以这个并查及不能进行路径压缩,但是我们要有保证深度,所以我们需要启发式合并。  

最终的时间复杂度:$O(q*(log(q))^2)$。

  1 #include<bits/stdc++.h>
  2 using namespace std;  
  3 #define rep(i,a,b) for(int i=a;i<=b;i++) 
  4 #define Rep(i,a,b) for(int i=a;i>=b;i--)  
  5 #define ms(i,a)    memset(a,i,sizeof(a))  
  6 #define gc()       getchar()  
  7 #define mid        (l+r>>1)  
  8 #define lc         (x<<1)  
  9 #define rc         (x<<1|1)
 10 #define pii        pair<int,int>   
 11 #define mp         make_pair
 12 #define fi         first 
 13 #define se         second 
 14 #define LL         long long 
 15 template<class T>void read(T &x){
 16     x=0; char c=0;  
 17     while (!isdigit(c)) c=gc();  
 18     while (isdigit(c)) x=x*10+(c^48),c=gc(); 
 19 }
 20 int const N=300000+3;  
 21 map<pii,int>mat;  
 22 vector<pii >a[N<<2];  
 23 map<pii,int> :: iterator it;  
 24 int n,f[N<<1],sz[N<<1],cntx[N<<1],cnty[N<<1];
 25 LL  ans[N],now;    
 26 int find(int x){return x==f[x]?  x: find(f[x]); }  
 27 void update(int x,int l,int r,int ll,int rr,pii t){
 28     if(ll<=l && r<=rr) {
 29         a[x].push_back(t); 
 30         return; 
 31     }
 32     if(ll<=mid) update(lc,l,mid,ll,rr,t);  
 33     if(rr>mid)  update(rc,mid+1,r,ll,rr,t); 
 34 }
 35 void merge(int x,int y,stack<pii> & st){
 36     int fx=find(x); 
 37     int fy=find(y);  
 38     if(fx!=fy){
 39         if(sz[fx]<sz[fy]) swap(fx,fy);  
 40         now-=1LL*cntx[fx]*cnty[fx];  
 41         now-=1LL*cntx[fy]*cnty[fy];  
 42         f[fy]=fx;  
 43         sz[fx]+=sz[fy];  
 44         cntx[fx]+=cntx[fy];  
 45         cnty[fx]+=cnty[fy];  
 46         now+=1LL*cntx[fx]*cnty[fx];  
 47         st.push(mp(fx,fy));  
 48     } 
 49 }
 50 void del(stack<pii> &st){
 51     while (!st.empty()){
 52         int fx=st.top().fi;  
 53         int fy=st.top().se;  
 54         st.pop();  
 55         now-=1LL*cntx[fx]*cnty[fx];  
 56         f[fy]=fy;  
 57         cntx[fx]-=cntx[fy];  
 58         cnty[fx]-=cnty[fy];  
 59         sz[fx]-=sz[fy];  
 60         now+=1LL*cntx[fx]*cnty[fx];  
 61         now+=1LL*cntx[fy]*cnty[fy];  
 62     }
 63 }
 64 void dfs(int x,int l,int r){
 65     
 66     stack<pii>st;  
 67     for(int i=0;i<a[x].size();i++) merge(a[x][i].fi,a[x][i].se,st);  
 68     if(l==r){
 69         ans[l]=now;
 70         del(st);    
 71         return ; 
 72     }
 73     dfs(lc,l,mid);  
 74     dfs(rc,mid+1,r);  
 75     del(st); 
 76 } 
 77     
 78 int main(){
 79     read(n);  
 80     rep(i,1,n){
 81         int x,y;  
 82         read(x); read(y);
 83         y+=300000;  
 84         if(mat.find(mp(x,y))==mat.end()) mat[mp(x,y)]=i;  
 85         else {
 86             update(1,1,n,mat[mp(x,y)],i-1,mp(x,y));  
 87             mat.erase(mp(x,y));   
 88         } 
 89     }
 90     for(it=mat.begin();it!=mat.end();it++){
 91         pii t=it->fi;  
 92         int g=it->se;  
 93         update(1,1,n,g,n,t);   
 94     }
 95     rep(i,1,300000) f[i]=i,sz[i]=1,cntx[i]=1;  
 96     rep(i,300000+1,600000) f[i]=i,sz[i]=1,cnty[i]=1;     
 97     dfs(1,1,n);  
 98     rep(i,1,n) printf("%lld ",ans[i]); 
 99     return 0; 
100 } 
View Code

 

 

posted @ 2019-04-04 16:49  zjxxcn  阅读(327)  评论(0编辑  收藏  举报