zoukankan      html  css  js  c++  java
  • 牛客练习赛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
    **/
    
    
  • 相关阅读:
    jmeter学习笔记(二)
    jmeter学习笔记(一)
    让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
    Fiddler抓包
    76. 最小覆盖子串
    Map中getOrDefault()与数值进行比较
    阻塞非阻塞与同步异步的区别
    81. 搜索旋转排序数组 II
    49. 字母异位词分组
    48. 旋转图像
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10812467.html
Copyright © 2011-2022 走看看