zoukankan      html  css  js  c++  java
  • 牛客 某练习赛 Data Structure

    Data Structure

    题目描述

    将一个非负整数序列划分为 (K) 段,分别计算出各段中的整数按位或的结果,然后再把这些结果按位与起来得到一个最终结果,把这个最终结果定义为这个序列的一个 (K−or−and) 值。

    比如序列为 ([1,5,9,2],K=2),如果划分为 ([1,5],[9,2]),那么 (K−or−and) 值为 ((1or5)and(9or2)=1)。当然划分可能不止一种,所以 (K−or−and) 值也可能不止一个。

    给定一个长度为 (N) 的非负整数序列 (A_1A_2A_3dots A_N),一个整数 (K) 和以下三种操作:

    1. 给定一个整数 (x) ,把序列中的所有数字按位或上 (x)。即(forall iin [1,N],A_i=A_i or x)

    2. 给定一个整数 (x),把序列中的所有数字按位与上 (x)。即(forall iin [1,N],A_i=A_i and x)

    3. 查询当前序列最大的 (K−or−and) 值。

    lililalala太菜了,他希望你来帮他解决这个问题。

    输入描述:

    第一行两个整数 (N,K(1le Kle N imes 2 imes 10^5)) -序列长度和划分的段数。
    第二行 (N)个整数 (A_1A_2A_3dots A_N( 0le A_1,A_2,A_3dots A_N<2^{31}))
    第三行一个整数 (Q(1le Qle 2 imes 10^5))--操作的数量。
    然后 (Q) 行其中第 (i)行为以下三种格式之一:
    (1x_i)--把序列中的所有数字按位或上 (x_i(0le x_i<2^{31}))
    (2x_i)--把序列中的所有数字按位与上 (x_i(0le x_i<2^{31}))
    (3)--查询当前序列最大的 (K−or−and) 值。

    输出描述:

    对于每次查询(操作 (3) )输出一行一个整数作为查询结果。


    昨天晚上云做题,看了看C和D

    然后成功嘴巴出做法,但是一直wa,今天顺手改一改,C比较简单,不管了

    先不管修改,我们直接看看怎么求原序列的答案

    显然可以按位贪心

    如果我们可以确定高(i)位的答案为(ans),那么考虑(i+1)位是否可以取(1),可以直接贪心考虑

    从左到右扫(A)数组,如果当前前缀异或值(x)可以拼出高(i+1)位的所有(1),就搞一个分割。

    这样显然可以最大化分割。

    然后复杂度(n log A_i)

    考虑操作每次会把所有的某一位取(0)或者(1),如果某一维被取过,这一位就不用管了。

    发现这样最多有(log A_i)个位被第一次全部取(0)或者(1)

    那么直接每次暴力就好了

    复杂度(O(nlog^2 A))


    Code:

    #include <cstdio>
    #include <cctype>
    const int SIZE=1<<21;
    char ibuf[SIZE],*iS,*iT;
    //#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
    #define gc() getchar()
    template <class T>
    void read(T &x)
    {
        x=0;char c=gc();
        while(!isdigit(c)) c=gc();
        while(isdigit(c)) x=x*10+c-'0',c=gc();
    }
    const int N=2e5+10;
    int yuy[32],a[N];
    int n,k,Q,ans;
    void getans()
    {
        ans=0;
        for(int j=30;~j;j--)
        {
            if(yuy[j]!=-1) continue;
            int cnt=0,x=0;
            ans|=1<<j;
            for(int i=1;i<=n;i++)
            {
                x|=a[i];
                if((ans&x)==ans) ++cnt,x=0;
            }
            if(cnt<k) ans^=1<<j;
        }
        for(int j=0;j<=30;j++)
        {
            if(yuy[j]==1)
                ans|=1<<j;
            else if(yuy[j]==0)
                ans&=~(1<<j);
        }
    }
    int main()
    {
        read(n),read(k);
        for(int i=1;i<=n;i++) read(a[i]);
        for(int j=0;j<=30;j++) yuy[j]=-1;
        getans();
        read(Q);
        for(int op,x,i=1;i<=Q;i++)
        {
            read(op);
            int flag=0;
            if(op==1)
            {
                read(x);
                for(int j=30;~j;j--)
                    if(x>>j&1)
                    {
                        if(yuy[j]==-1) flag=1;
                        yuy[j]=1;
                    }
                if(flag) getans();
            }
            else if(op==2)
            {
                read(x);
                for(int j=30;~j;j--)
                    if(!(x>>j&1))
                    {
                        if(yuy[j]==-1) flag=1;
                        yuy[j]=0;
                    }
                if(flag) getans();
            }
            else
                printf("%d
    ",ans);
            for(int j=0;j<=30;j++)
            {
                if(yuy[j]==1)
                    ans|=1<<j;
                else if(yuy[j]==0)
                    ans&=~(1<<j);
            }
        }
        return 0;
    }
    

    2019.5.4

  • 相关阅读:
    【秒懂音视频开发】03_重识音频
    【秒懂音视频开发】02_重识声音
    【秒懂音视频开发】01_移动通信技术的发展
    [mysql]错误解决之"Failed to start MySQL Server"
    Ubuntu 将Python从默认的2.7升级到3.* 版本
    宝塔面板后台设置免费SSL证书Let's Encrypt(三)
    Let's Encrypt 证书申请及配置(二)
    快速签发 Let's Encrypt 证书指南(一)
    DJANGO中多种重定向方法使用
    反解法|逆向思维
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10808931.html
Copyright © 2011-2022 走看看