牛客练习赛45D 链表+模拟

题解 牛客练习赛45D

考点:链表?瞎搞
链接:https://ac.nowcoder.com/acm/contest/847/D
题意:数组,提供三个操作,全部数与、或上一个x,查询数组分成k份的最大k-or-and具体见原题。
思路:无聊正好看见有比赛。。寻思练练手。。结果敲了个水题就被这题卡住了。。下来写了很久才过。
首先考虑到实际上参与答案计算的只有一开始大于k的位,于是建一个链表(偷懒用了vector,毕竟只有31个数),在操作的过程中维护这个链表。答案分两部分计算,一部分是全都一样的,一部分是链表里的。在统计答案的时候看看是否是最新的,不是的就up一下(实际上最多up31次)。up的时候纯暴力,从高位到低位一步步尝试就行了。。实际复杂度高达O(n(logn)^3)。。但是还是水过去了,暴力check的地方应该可以优化一下。。

#include <bits/stdc++.h>
#define X first
#define Y second
#define PB push_back
#define LL long long
#define pii pair<int,int>
#define MEM(x,y) memset(x,y,sizeof(x))
#define bug(x) cout<<"debug "#x" is "<<x<<endl;
#define FIO ios::sync_with_stdio(false);
#define ALL(x) x.begin(),x.end()
using namespace std;
const int maxn=200007;
const int mod=1e9+7;
const LL inf=2e18;
int n,k,q,x,y,a[maxn];
bool bit[31][maxn];
int is[31],push_down=0,cnt[31],real_cnt[31];
vector<int> lis;
void or_update(int x,int y){
    if(y==0)return;
    auto it=find(ALL(lis),x);
    if(is[x]==-1&&it!=lis.end()){
        lis.erase(it);
        push_down=0;
    }
    is[x]=1;
}
void and_update(int x,int y){
    if(y==1)return;
    auto it=find(ALL(lis),x);
    if(is[x]==-1&&it!=lis.end()){
        lis.erase(it);
        push_down=0;
    }
    is[x]=0;
}
bool tmp[maxn];
bool check(const vector<int> &ck,int x){
    int cnt=0,siz=0,nn=ck.size(),h=0;
    int S[32]={0};
    for(int i=1;i<=n;i++){
        if(siz<nn){
            for(int c:ck){
                if(bit[c][i]==1&&S[c]==0) S[c]=1,siz++;
            }
        }
        if(bit[x][i]==1)h=1;
        if(siz==nn&&h==1){
            cnt++,MEM(S,0),siz=0,h=0;
            if(cnt>=k)return 1;
        }
    }
    return cnt>=k;
}
void update(){
    vector<int> ck;
    MEM(cnt,0);
    if(lis.size()>0)cnt[lis[0]]=1,ck.PB(lis[0]);
    for(int j=1;j<lis.size();j++){
        int y=lis[j];
        if(check(ck,y))ck.PB(y),cnt[y]=1;
    }
    push_down=1;
}
LL get_ans(){
    if(push_down==0)update();
    LL ret=0;
    for(int i=0;i<31;i++){
        if(is[i]==-1&&cnt[i]==1){
            ret+=(1LL<<i);
        }
        else if(is[i]==1){
            ret+=(1LL<<i);
        }
    }
    return ret;
}
int main(){
    FIO;
    MEM(is,-1);
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++){
        for(int j=0;j<=30;j++)
            bit[j][i]=((a[i]>>j)&1),real_cnt[j]+=((a[i]>>j)&1);
    }
    for(int j=30;j>=0;j--)if(real_cnt[j]>=k)lis.PB(j);
    cin>>q;
    while(q--){
        cin>>x;
        if(x==1){
            cin>>y;
            for(int i=0;i<31;i++)or_update(i,((y>>i)&1));
        }
        else if(x==2){
            cin>>y;
            for(int i=0;i<31;i++)and_update(i,((y>>i)&1));
        }
        else{
            cout<<get_ans()<<endl;
        }
    }
}
/**
2 1
11 30
1
3
**/

posted @ 2019-05-05 13:28  zhangxianlong  阅读(223)  评论(0编辑  收藏  举报