Vertices in the Pocket 暴力代码

China☆狼群 提交于 2020-03-08 16:51:36
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+14;
int father[maxn];
int cnt[maxn];
int num[maxn];
int isRoot[maxn];
int N,Q;
int block;
bool cmp (int a,int b) {
    return a>b;
}
void init () {
    for (int i=1;i<=N;i++) {
        cnt[i]=0;
        num[i]=1;
        father[i]=i;
        isRoot[i]=1;
    }
    block=N;
}

int findfather (int x) {
    int a=x;
    while (x!=father[x]) x=father[x];
    while (a!=father[a]) {
        int z=a;
        a=father[a];
        father[z]=x;
    }
    return x;
}

void Union (int a,int b) {
    int faA=findfather(a);
    int faB=findfather(b);
    if (faA==faB) {
        cnt[faA]++;
        return;
    }
    if (faA<faB) swap(faA,faB);
    father[faA]=faB;
    block--;
    num[faB]+=num[faA];
    cnt[faB]=cnt[faB]+cnt[faA]+1;
    isRoot[faA]=0;
}

int getMin (int k) {
    return max(1,block-k); 
}

int getMax (int k) {
    int ans=0;
    for (int i=1;i<=N;i++)
        ans+=isRoot[i]*(num[i]*(num[i]-1)/2-cnt[i]);
    if (k<=ans) return block;
    vector<int> vi;
    for (int i=1;i<=N;i++)
        if (isRoot[i]) vi.push_back(num[i]);
    sort(vi.begin(),vi.end(),cmp);
    k-=ans;
    int ck;
    for (ck=0;ck<block-1;ck++) {
        k-=(vi[ck]*vi[ck+1]);
        vi[ck+1]+=vi[ck];
        if (k<=0) break;
    }
    return block-ck-1;
    
}

int main () {
    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&N,&Q);
        init(); 
        int a,b;
        int query;
        while (Q--) {
            scanf("%d",&query);
            if (query==1) {
                scanf("%d%d",&a,&b);
                Union(a,b);
            }
            else {
               scanf("%d",&a);
               printf("%d %d\n",getMin(a),getMax(a));
            }
        }
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!