• [位运算]签到题


    题目描述

    作为一道签到题,自然只能包含最基本的算法。本题的任务很简单,给定一个长度为n的序列a,你要将其排序。
    由于出题人很菜,不会排序算法,他决定自己编一个。他想找到一个数x,使得序列中的所有数字都异或上x后序列恰好按从小到大排列。
    顺带,这个序列会被进行若干次修改,每次修改后你需要回答当前是否存在一个x满足序列中数字异或上x后按从小到大排列,如果有,请你给出最小的x。

    输入

    第一行一个正整数n。
    第二行n个非负整数,表示序列a。
    第三行一个非负整数q,表示修改次数。
    接下来q行,每行一个正整数x和一个非负整数y,表示将序列中第x个元素修改为y

    输出

    输出q+1行,每行一个整数,第一行表示一开始最小的合法x,之后q行依次表示每次修改后最小的合法x,如果不存在则这一行输出−1。

    样例输入

    3
    0 1 4
    3
    2 7
    3 3
    1 4
    

    样例输出

    0
    2
    -1
    4
    

    提示

    对于100%的数据,n,m≤106,所有数字不超过230。
    请注意输入输出效率对程序运行时间的影响。

    两个数的大小差异在于其二者二进制位相异的最高一位,若在这一位异或1,两数的大小关系能得到反转,在除这位外的任何一位异或0/1,大小关系不会改变
    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
     
    int n,a[1000005];
    int cnt[35][5];
     
    void solve(){
      int ret=0;
      for(int i=30;i>=0;--i){
        if(cnt[i][1]&&cnt[i][0]){
            printf("-1
    ");
            return;
        }
        if(cnt[i][1]){
            ret|=(1<<i);
        }
      }
      printf("%d
    ",ret);
      return;
    }
     
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
     
        for(int i=2;i<=n;++i){
            for(int j=30;j>=0;--j){
                if((a[i]^a[i-1])&(1<<j)){
                    cnt[j][a[i-1]>a[i]]++;
                    break;
                }
            }
        }
     
        solve();
     
        int q;scanf("%d",&q);
        int x,y;
        while(q--){
            scanf("%d%d",&x,&y);
            if(x>1){
                for(int i=30;i>=0;--i){
                    if((a[x]^a[x-1])&(1<<i)){
                        cnt[i][a[x-1]>a[x]]--;
                        break;
                    }
                }
                for(int i=30;i>=0;--i){
                    if((y^a[x-1])&(1<<i)){
                        cnt[i][a[x-1]>y]++;
                        break;
                    }
                }
            }
            if(x<n){
                for(int i=30;i>=0;--i){
                    if((a[x]^a[x+1])&(1<<i)){
                        cnt[i][a[x]>a[x+1]]--;
                        break;
                    }
                }
                for(int i=30;i>=0;--i){
                    if((y^a[x+1])&(1<<i)){
                        cnt[i][y>a[x+1]]++;
                        break;
                    }
                }
            }
            a[x]=y;
            solve();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    用JS获取地址栏参数的方法(超级简单)
    返回前一页并刷新页面方法
    js 弹出确认 取消对话框
    微信“无法回答问题设置”失效
    百度地图api学习平台
    JQuery 定时器 (Jquery Timer 插件)
    select 框option添加属性 js计算价格 保持两位小数
    修改织梦分页标签样式
    一键导航
    关于memset赋值无穷大无穷小
  • 原文地址:https://www.cnblogs.com/lllxq/p/10509774.html
Copyright © 2020-2023  润新知