poj 2985

来源:互联网 发布:电脑电子书阅读软件 编辑:程序博客网 时间:2024/06/04 01:06

今天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;}
0 0
原创粉丝点击