码迷,mamicode.com
首页 > 其他好文 > 详细

机房测试:Dove打扑克(vector暴力)

时间:2019-11-08 20:42:21      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:display   iter   open   --   get   define   work   pac   查找   

题目:

技术图片

 

 技术图片

 

 题目:

我怎么也不会想到,这道题的正解会如此的暴力。。。

一开始我的做法是开一个桶记录一下每种元素的出现次数,每次查找的时候,枚举一个元素x,查询大于等于x+c的个数。

这样是n*m的,但是其实不同的元素个数只有sqrt(n)个,因为:1+2+3+……x=n,x最多为sqrt(n)

所以用一个vector或者set记录一下目前有值的元素是哪些,每一次只for那些即可。

查询的时候用树状数组维护即可。

复杂度:O(m*sqrt(n)*logn)

技术图片
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ri register int
#define N 100005
int tong[N],cnt[N],sum[N],fa[N],n,m,t[N*4];
set<int> st;
int read()
{
    int x=0,fl=1; char ch=getchar();
    while(ch<0 || ch>9) { if(ch==-) fl=-1; ch=getchar(); }
    while(ch<=9 && ch>=0) x=x*10+ch-0,ch=getchar();
    return x*fl;
}
int find(int x) { if(x==fa[x]) return x; return fa[x]=find(fa[x]); }
void modify(int x,int v)
{
    while(x<=n) { t[x]+=v; x+=(x&-x); }
}
ll query(int x)
{
    ll ans=0;
    while(x>0) { ans+=t[x]; x-=(x&-x); }
    return ans;
}
ll work(int c)
{
    ll ans=0;
    if(c==0){
        ll x=query(n);
        return x*(x-1)/2;
    }
    set<int>::iterator it=st.begin();//set保证插入的元素都是有序的 
    for(it;it!=st.end();++it){
        int tp=*it;//这样就可以遍历每一个元素 
        if(tp+c>n) break;
        ll x=query(n)-query(tp+c-1);
        ans+=1ll*x*tong[tp];
    }
    return ans;
}
int main()
{
    freopen("cards.in","r",stdin);
    freopen("cards.out","w",stdout);
    n=read(); m=read();
    for(ri i=1;i<=n;++i) fa[i]=i,cnt[i]=1;
    tong[1]=n; modify(1,n); st.insert(1);
    while(m--){
        int op=read();
        if(op==1){
            int x=read(), y=read();
            int f1=find(x),f2=find(y);
            if(f1==f2) continue;
            tong[cnt[f2]]--; tong[cnt[f1]]--;
            modify(cnt[f2],-1); modify(cnt[f1],-1);
            if(!tong[cnt[f2]]) st.erase(cnt[f2]);
            if(!tong[cnt[f1]]) st.erase(cnt[f1]);
            cnt[f2]+=cnt[f1];
            if(!tong[cnt[f2]]) st.insert(cnt[f2]);
            modify(cnt[f2],1);
            tong[cnt[f2]]++;
            fa[f1]=f2;
            cnt[f1]=-1;
        }
        else{
            int c=read();
            printf("%lld\n",work(c));
        }
    }
    return 0;
}
/*
7 5
2 1
1 4 1
2 3
2 1
2 0
*/
View Code

 

机房测试:Dove打扑克(vector暴力)

标签:display   iter   open   --   get   define   work   pac   查找   

原文地址:https://www.cnblogs.com/mowanying/p/11822893.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!