POJ 2985 The kth Largest Group

POJ_2985

    这个题目以cats的个数为关键字建立线段树去做,我为了练一下昨天刚学的SBT所以就用SBT写了,不过SBT的效率要低一些。

#include<stdio.h>
#include<string.h>
#define MAXD 200010
#define MAXM 400010
int N, M, T, node, p[MAXD], left[MAXM], right[MAXM], key[MAXM], size[MAXM], s[MAXM];
int find(int x)
{
return p[x] == x ? x : (p[x] = find(p[x]));
}
void left_rotate(int &T)
{
int k = right[T];
right[T] = left[k];
left[k] = T;
size[k] = size[T];
size[T] = size[left[T]] + size[right[T]] + 1;
T = k;
}
void right_rotate(int &T)
{
int k = left[T];
left[T] = right[k];
right[k] = T;
size[k] = size[T];
size[T] = size[left[T]] + size[right[T]] + 1;
T = k;
}
void maintain(int &T, int flag)
{
if(flag == 0)
{
if(size[left[left[T]]] > size[right[T]])
right_rotate(T);
else if(size[right[left[T]]] > size[right[T]])
left_rotate(left[T]), right_rotate(T);
else
return ;
}
else
{
if(size[right[right[T]]] > size[left[T]])
left_rotate(T);
else if(size[left[right[T]]] > size[left[T]])
right_rotate(right[T]), left_rotate(T);
else
return ;
}
maintain(left[T], 0);
maintain(right[T], 1);
maintain(T, 0);
maintain(T, 1);
}
void add(int &T, int v)
{
T = ++ node;
size[T] = 1;
key[T] = v;
left[T] = right[T] = 0;
}
void Insert(int &T, int v)
{
if(T == 0)
{
add(T, v);
return ;
}
++ size[T];
if(v < key[T])
Insert(left[T], v);
else
Insert(right[T], v);
maintain(T, v >= key[T]);
}
int Delete(int &T, int v)
{
-- size[T];
if(key[T] == v || (v < key[T] && left[T] == 0) || (v > key[T] && right[T] == 0))
{
int k = key[T];
if(left[T] == 0 || right[T] == 0)
T = left[T] + right[T];
else
key[T] = Delete(left[T], key[T] + 1);
return k;
}
else if(v < key[T])
return Delete(left[T], v);
else
return Delete(right[T], v);
}
int select(int &T, int k)
{
int n = size[left[T]] + 1;
if(k == n)
return key[T];
if(k < n)
return select(left[T], k);
else
return select(right[T], k - n);
}
void init()
{
int i;
T = node = left[0] = right[0] = size[0] = 0;
for(i = 1; i <= N; i ++)
{
p[i] = i, s[i] = 1;
Insert(T, 1);
}
}
void solve()
{
int i, j, k, x, y, tx, ty;
for(i = 0; i < M; i ++)
{
scanf("%d", &j);
if(j == 0)
{
scanf("%d%d", &x, &y);
tx = find(x), ty = find(y);
if(tx != ty)
{
Delete(T, s[tx]);
Delete(T, s[ty]);
p[ty] = tx;
s[tx] += s[ty];
Insert(T, s[tx]);
}
}
else
{
scanf("%d", &k);
printf("%d\n", select(T, size[T] - k + 1));
}
}
}
int main()
{
while(scanf("%d%d", &N, &M) == 2)
{
init();
solve();
}
return 0;
}


原文地址:https://www.cnblogs.com/staginner/p/2408008.html