LA4730 UVA1455 线段树+并查集

以y轴建线段树 把坐标*2 初始化各节点 洲,城市 数目为0
并查集维护每一个连通块的 y坐标最大值最小值(x坐标没用)城市数目
合并时 如果是一个洲(城市数大于1) 线段树对应区间减掉该洲城市数
然后将两个洲合并,再在线段树对应区间增加大洲的城市数
(区间城市数不等于子区间城市数之和)

#include 

using namespace std;
const int Maxn=2e6+80;
int f[Maxn];
struct node
{
    int l,r,city,zhou,addc,addz;
    int mid()
    {
        return (l+r)/2;
    }
} tree[Maxn<<2];
struct point
{
    int maxn,minv,city,zhou;
};
point p[Maxn];
int findset(int u)
{
    return u==f[u]?u:f[u]=findset(f[u]);
}
void build(int node,int l,int r)
{
    tree[node].l=l,tree[node].r=r;
    tree[node].city=tree[node].zhou=tree[node].addc=tree[node].addz=0;
    if(l==r) return;
    build(node<<1,l,(r+l)>>1);
    build(node<<1|1,(r+l)/2+1,r);
}
void pushdown(int node)
{
    if(tree[node].addc)
    {
        tree[node<<1].city+=tree[node].addc;
        tree[node<<1|1].city+=tree[node].addc;
        tree[node<<1].addc+=tree[node].addc;
        tree[node<<1|1].addc+=tree[node].addc;
        tree[node].addc=0;
    }
    if(tree[node].addz)
    {
        tree[node<<1].zhou+=tree[node].addz;
        tree[node<<1|1].zhou+=tree[node].addz;
        tree[node<<1].addz+=tree[node].addz;
        tree[node<<1|1].addz+=tree[node].addz;
        tree[node].addz=0;
    }
}
void update(int node,int l,int r,int city,int zhou)
{
    if(tree[node].l==l&&r==tree[node].r)
    {
        tree[node].city+=city;
        tree[node].zhou+=zhou;
        tree[node].addc+=city;
        tree[node].addz+=zhou;
        return ;
    }
    pushdown(node);
    int mid=tree[node].mid();
    if(mid1|1,l,r,city,zhou);
    }
    else if(mid>=r)
    {
        update(node<<1,l,r,city,zhou);
    }
    else
    {
        update(node<<1,l,mid,city,zhou);
        update(node<<1|1,mid+1,r,city,zhou);
    }
}
int query(int node,int l,int r)
{
    if(tree[node].l==l&&r==tree[node].r)
    {
        return node;
    }
    int mid=tree[node].mid();
    pushdown(node);
    if(mid1|1,l,r);
    }
    else if(mid>=r)
    {
        query(node<<1,l,r);
    }
    else
    {
        query(node<<1,l,mid);
        query(node<<1|1,mid+1,r);
    }
}
void un(int x,int y)
{
    int _x=findset(x),_y=findset(y);
    if(f[_x]==f[_y])
    {
        return ;
    }
    f[_x]=_y;
    if(p[_x].city>1)
        update(1,p[_x].minv,p[_x].maxn,-p[_x].city,-1);
    if(p[_y].city>1)
        update(1,p[_y].minv,p[_y].maxn,-p[_y].city,-1);
    p[_y].maxn=max(p[_x].maxn,p[_y].maxn);
    p[_y].minv=min(p[_y].minv,p[_x].minv);
    p[_y].city+=p[_x].city;
    update(1,p[_y].minv,p[_y].maxn,p[_y].city,1);
}
int t,n,m;
int yy[Maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {

        int x,y,Max=0;
        scanf("%d",&n);
        for(int i =1; i<=n; ++i) f[i]=i;
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d%d",&x,&y);
            yy[i]=y*2;
            Max=max(Max,yy[i]);
            p[i].minv=p[i].maxn=y*2;
            p[i].city=1;
            p[i].zhou=1;
        }
        build(1,0,Max);
        for(int i = 1; i<= n; ++i)
            update(1,yy[i],yy[i],1,1);
        scanf("%d",&m);
        char ch[10];
        double pos;
        for(int i = 0; i < m; ++i)
        {
            scanf("%s",ch);
            if(ch[0]=='r')
            {
                scanf("%d%d",&x,&y);
                un(x+1,y+1);
            }
            else
            {
                scanf("%lf",&pos);
                if(pos*2>Max) printf("0 0\n");
                else
                {
                    int no=query(1,pos*2,pos*2);
                    printf("%d %d\n",tree[no].zhou,tree[no].city);
                }
            }
        }
    }
    return 0;
}

你可能感兴趣的:(白书,Trie,并查集,线段树)