习题:Make Them Similar(折半搜索)

题目

传送门

思路

首先如果不考虑数据范围

很容易有一个\(O(n*2^{30})\)的算法

此时我们想,如果只有值域只有\(2^{15}\) 该有多好

比较容易的可以想到折半搜索

我们用差分对数组和操作进行处理

这里的操作指的是每一位上异或1会是什么情况

最后的答案一定是全是0的数组

用map维护一下另一半就行了

总时间复杂度\(O(n*2^{15}*15)\)

这里作者脑抽了一下,将操作用vector来存,其实可以用一个数的二进制来表示的

代码

#include<iostream>
#include<vector>
#include<map>
using namespace std;
int n;
int a[205];
int s[205];
struct node
{
    int a[205];
    node()
    {
        for(int i=1;i<=n;i++)
            a[i]=0;
    }
    friend bool operator < (const node &a,const node &b)
    {
        for(int i=1;i<=n;i++)
        {
            if(a.a[i]==b.a[i])
                continue;
            return a.a[i]<b.a[i];
        }
        return 0;
    }
    friend bool operator == (const node &a,const node &b)
    {
        for(int i=1;i<=n;i++)
            if(a.a[i]!=b.a[i])
                return 0;
        return 1;
    }
    friend node operator + (const node &a,const node &b)
    {
        node c;
        for(int i=1;i<=n;i++)
            c.a[i]=a.a[i]+b.a[i];
        return c;
    }
}add[40];
node bas;
map<node,vector<int> >f;
int count(int val)
{
    int tot=0;
    while(val)
    {
        if(val&1)
            tot++;
        val>>=1;
    }
    return tot;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        s[i]=count(a[i]);
    }
    n--;
    for(int i=1;i<=n;i++)
        s[i]=s[i+1]-s[i];
    for(int i=1;i<=n;i++)
        bas.a[i]=s[i];
    for(int i=0;i<=29;i++)
    {
        for(int j=1;j<=n+1;j++)
        {
            if(((a[j]&(1<<i))^(1<<i))==0)
                add[i].a[j]=-1;
            else
                add[i].a[j]=1;
        }
        for(int j=1;j<=n;j++)
            add[i].a[j]=add[i].a[j+1]-add[i].a[j];
    }
    for(int i=0;i<(1<<15);i++)
    {
        node t;
        vector<int> v;
        for(int j=0;(1<<j)<=i;j++)
            if(i&(1<<j))
            {
                t=t+add[15+j];
                v.push_back(15+j);
            }
        f[t]=v;    
    }
    cout<<endl;
    for(int i=0;i<(1<<15);i++)
    {
        node t=bas;
        vector<int> v;
        for(int j=0;(1<<j)<=i;j++)
            if(i&(1<<j))
            {
                t=t+add[j];
                v.push_back(j);
            } 
        for(int j=1;j<=n;j++)
            t.a[j]=-t.a[j];
        if(f.count(t)>0)
        {
            long long ans=0;
            for(int i=0;i<v.size();i++)
                ans=ans+(1<<v[i]);
            for(int i=0;i<f[t].size();i++)
            {
                ans=ans+(1<<f[t][i]);
            }
            cout<<ans;
            return 0;
        }
    }
    cout<<"-1";
    return 0;
}
posted @ 2020-07-20 10:49  loney_s  阅读(109)  评论(0)    收藏  举报