poj 2985 分类: poj 2015-03-07 21:25 47人阅读 评论(0) 收藏
今天xjz大爷说写写平衡树,结果此题卡平衡树常数,
听说sbt都要卡常数才能过,想想都觉得不可思议,给跪了
正解是并查集+树状数组+二分答案。
都不难写,但我觉得这题卡平衡树还挺是挺坑的。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iostream>
const int MAXN = 200005;
int fa[MAXN] = {0} ,cnt[MAXN] = {0} ,tot;
int ta[MAXN] = {0};
int n , m;
inline int lowbit(const int &x)
{
return x&(-x);
}
inline void swap(int &a,int &b)
{
int tmp; tmp = a, a = b ,b = tmp;
}
inline void add(int x , const int &val)
{
while(x <= n)
{
ta[x] += val;
x += lowbit(x);
}
}
inline int count(int x)
{
int ret = 0;
while(x > 0)
{
ret += ta[x];
x -= lowbit(x);
}
return ret;
}
inline int find_fa(const int x)
{
if(fa[x] == x) return x;
else
{
fa[x] = find_fa(fa[x]); return fa[x];
}
}
inline void gather(const int &a,const int &b)
{
int u = find_fa(a) , v =find_fa(b);
if(u == v)return;
if(v < u)swap(u ,v);//make sure u<v
add(cnt[v] , -1); add(cnt[u], -1); add(cnt[u] + cnt[v], +1);
cnt[u] += cnt[v] , cnt[v] = 0;
fa[v] = u; tot --;
}
inline int find(const int &x)
{
int l = 1, r = n;
if(x <= count(1))return 1;
while(l + 1 != r)
{
int mid = (l + r)>>1;
if(x <= count(mid)) r = mid;
else l = mid;
}
return r;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("poj2985.in","r",stdin);
freopen("poj2985.out","w",stdout);
#endif
scanf("%d%d",&n,&m);tot = n;
for(int i = 1;i <= n;i++){fa[i] = i;cnt[i] = 1;}
add(1 , n);
for(int i = 1;i <= m;i++)
{
int a , b ,c;
scanf("%d",&c);
if(c == 0)
{
scanf("%d%d",&a,&b);gather(a,b);
}
else
{
scanf("%d",&a); printf("%d\n",find(tot + 1 - a));;
}
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。