【GDOI2017 day2】凡喵识图 二进制切分

题面

1146820-20170505220840586-1304981655.jpg
1146820-20170505220919836-309050152.jpg

100

有一个显然的做法是\(O(n^2)\)
想办法优化这个做法:
我们给一个64位整数,切分成四个16位整数。
那么如果两个64位整数符合汉明距离为3的话,那么两者切分的四个16位整数中;
至少存在一个16位整数相等。
那么我们用这个16位整数为引索,遍历所有可能的,就能优化遍历次数了。
由于数据近似随机,所以这个方法是可以过的。

Code

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const int inf=0x7fffffff;
const char* fin="2.in";
const char* fout="2.out";
const int maxn=150007,maxh=maxn*3+7;
int n,ne[maxn][4],id,bz[maxn];
ull a[maxn][4],b[maxn];
map<ull,int> mp[4];
bool judge(ull a,ull b){
    ull c=a^b;
    int x=0;
    while (c){
        if (++x>3) return false;
        c-=c&-c;
    }
    return x==3;
}
int main(){
    freopen(fin,"r",stdin);
    freopen(fout,"w",stdout);
    scanf("%d",&n);
    ull m=1<<16;
    fo(i,1,n){
        ull x;
        id++;
        scanf("%llu",&x);
        b[i]=x;
        int ans=0;
        fo(j,0,3) a[i][j]=x%m,x/=m;
        fo(j,0,3){
            if (mp[j].find(a[i][j])!=mp[j].end()){
                int k=mp[j][a[i][j]];
                ne[i][j]=k;
                for(;k;k=ne[k][j]){
                    if (bz[k]==id) continue;
                    bz[k]=id;
                    if (judge(b[i],b[k])) ans++;
                }
            }mp[j][a[i][j]]=i;
        }
        printf("%d\n",ans);
    }
    return 0;
}

转载于:https://www.cnblogs.com/hiweibolu/p/6815189.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值