LA_4730 Kingdom 并查集+树状数组

给定N个点的坐标,代表N各城市,有M种操作,共分两种,一种是连线,把两个点连起来(一旦构成连通图,这个连通图即为一个州),还有种询问操作,为y=c,(c为小数部分恒为.5的实数),问y=c这条线经过了多少个大周,这些州总共有多少个城市

很明显要用到并查集,比较好的做法是把并查集落实到线段树上,并查集维护的是每个集合的最大y和最小y,以及rank表示集合数目。但是线段树要用到离散化、

然后参照一个用树状数组的博客,其实思路差不多,都是把每次的变更落实到树上

不过这个树状数组跟之前写的不一样,这个是改段查点型的,之前的是改点查段型的,其实只要改一下辅助数组的定义即可,在这个树状数组里面,把辅助数组d当做从1到当前所有的变更,每次更新时从当前往递减方向,所以,为了得到某个点值,必须把当前点以及当前之前的变更都加起来。

所以这个

add(int loc,int v)

{

    while (loc>0){d[loc]+=v;loc-=lowbit(loc);}

}

query(int loc)

{

   int ret=0;

   while (loc<n) {ret+=d[loc];loc+=lowbit(loc);}

   return ret;

}

因为给定的数是.5的实数,故意把坐标往后压一位即可,把每一个小格子往后压成一个点即可

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 int n,m;
  8 int f[100010],rank[100010],y1[100010],y2[100010];
  9 void init()
 10 {
 11     for (int i=0;i<=n;i++){
 12         f[i]=i;
 13         rank[i]=1;
 14     }
 15 }
 16 int findset(int x)
 17 {
 18     if (x!=f[x]){
 19         f[x]=findset(f[x]);
 20     }
 21     return f[x];
 22 }
 23 int lowbit(int x)
 24 {
 25     return x&(-x);
 26 }
 27 struct bit
 28 {
 29     int d[100010];
 30     int limit;
 31     void clear()
 32     {
 33         memset(d,0,sizeof d);
 34     }
 35     void add(int L,int R,int v){
 36         while (R>=1){
 37             d[R]+=v;
 38             R-=lowbit(R);
 39         }
 40         while (L>=1){
 41             d[L]+=-v;
 42             L-=lowbit(L); //L这里不能算点,因为每个格子都往后压,每个点x,就代表x-1到x这个区间,所以在这里可以抵消L的格子的影响
 43         }
 44     }
 45     int query(int x)
 46     {
 47         int ret=0;
 48         while (x<=limit){
 49             ret+=d[x];
 50             x+=lowbit(x);
 51         }
 52         return ret;
 53     }
 54 }city,state;
 55 void unit(int r1,int r2)
 56 {
 57     f[r1]=r2;
 58     rank[r2]+=rank[r1];
 59 }
 60 int main()
 61 {
 62     int t;
 63     scanf("%d",&t);
 64     int a,b;
 65     double c;
 66     char ch[10];
 67     while (t--)
 68     {
 69         city.clear();
 70         state.clear();
 71         scanf("%d",&n);
 72         init();
 73         int maxn=0;
 74         for (int i=0;i<n;i++){
 75             scanf("%d%d",&a,&b);
 76             y1[i]=b;y2[i]=b;
 77             maxn=max(maxn,b);
 78         }
 79         city.limit=state.limit=maxn;
 80         scanf("%d",&m);
 81         for (int i=1;i<=m;i++){
 82             scanf("%s",ch);
 83             if (ch[0]=='r'){
 84                 scanf("%d%d",&a,&b);
 85                 int r1=findset(a);
 86                 int r2=findset(b);
 87                 if (r1==r2) continue;
 88                 if (rank[r1]==1 && rank[r2]==1){
 89                     unit(r1,r2);
 90                     y1[r2]=min(y1[r2],y1[r1]);
 91                     y2[r2]=max(y2[r2],y2[r1]);
 92                     city.add(y1[r2],y2[r2],1);
 93                     state.add(y1[r2],y2[r2],rank[r2]);
 94                 }
 95                 else
 96                 if (rank[r1]==1 || rank[r2]==1){
 97                     if (rank[r1]==1) swap(r1,r2);
 98                     city.add(y1[r1],y2[r1],-1);
 99                     state.add(y1[r1],y2[r1],-rank[r1]);
100                     unit(r1,r2);
101                     y1[r2]=min(y1[r1],y1[r2]);
102                     y2[r2]=max(y2[r1],y2[r2]);
103                     city.add(y1[r2],y2[r2],1);
104                     state.add(y1[r2],y2[r2],rank[r2]);
105                 }
106                 else
107                 {
108                     city.add(y1[r1],y2[r1],-1);
109                     state.add(y1[r1],y2[r1],-rank[r1]);
110 
111                     city.add(y1[r2],y2[r2],-1);
112                     state.add(y1[r2],y2[r2],-rank[r2]);
113 
114                     unit(r1,r2);
115                     y1[r2]=min(y1[r1],y1[r2]);
116                     y2[r2]=max(y2[r1],y2[r2]);
117                     city.add(y1[r2],y2[r2],1);
118                     state.add(y1[r2],y2[r2],rank[r2]);
119                 }
120             }
121             else {
122                 scanf("%lf",&c);
123                 int tmp=c;
124                 tmp++;
125                 printf("%d %d\n",city.query(tmp),state.query(tmp));
126             }
127         }
128     }
129     return 0;
130 }
posted @ 2014-07-16 14:12  KRisen  阅读(402)  评论(0编辑  收藏  举报