POJ 2985 The k-th Largest Group 线段树求整体第K大

179 阅读1分钟

 维护size即可,更像是简单的划分树,不多说了。

感觉算是比较典型的应用了,可是没想出来线段树做,一直尝试着用伸展树水过去,TLE了N发之后才明白毕竟土洋。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 6000007

using namespace std;

int fa[200010];
int re[200010];
int num[200010];

int Find(int x)
{
    int t = x;

    while(x != fa[x])
        x = fa[x];
    int g;

    while(t != fa[t])
        g = fa[t],fa[t] = x,t = g;
    return x;
}

int st[800010];

void Init(int site,int l,int r)
{
    if(l == r)
    {
        st[site] = num[l];
        return ;
    }

    int mid = (l+r)>>1;

    Init(site<<1,l,mid);
    Init(site<<1|1,mid+1,r);

    st[site] = st[site<<1] + st[site<<1|1];
}

void Updata(int site,int l,int r,int k,int c)
{
    if(l == r)
    {
        st[site] += c;
        return ;
    }

    int mid = (l+r)>>1;
    if(k <= mid)
        Updata(site<<1,l,mid,k,c);
    else
        Updata(site<<1|1,mid+1,r,k,c);

    st[site] = st[site<<1] + st[site<<1|1];
}

int Query(int site,int l,int r,int k)
{
    if(l == r)
        return l;
    int mid = (l+r)>>1;

    if(k <= st[site<<1|1])
        return Query(site<<1|1,mid+1,r,k);
    return Query(site<<1,l,mid,k-st[site<<1|1]);
}

int main()
{
    int n,m,i,u,v,c,k,fu,fv;

    scanf("%d %d",&n,&m);

    for(i =1; i <= n; ++i)
        fa[i] = i,re[i] = 1,num[i] = 0;

    num[1] = n;

    Init(1,1,n);

    while(m--)
    {
        scanf("%d",&c);

        if(c == 1)
        {
            scanf("%d",&k);
            printf("%d\n",Query(1,1,n,k));
        }
        else
        {
            scanf("%d %d",&u,&v);
            fu = Find(u);
            fv = Find(v);

            if(fu != fv)
            {
                Updata(1,1,n,re[fu],-1);
                Updata(1,1,n,re[fv],-1);
                re[fv] += re[fu];
                fa[fu] = fv;
                Updata(1,1,n,re[fv],1);
            }
        }
    }

    return 0;
}