[位运算]签到题

题目描述

作为一道签到题,自然只能包含最基本的算法。本题的任务很简单,给定一个长度为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\n");
        return;
    }
    if(cnt[i][1]){
        ret|=(1<<i);
    }
  }
  printf("%d\n",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;
}

原文地址:https://www.cnblogs.com/lllxq/p/10509774.html

时间: 2024-10-28 05:46:31

[位运算]签到题的相关文章

数学,位运算,典型题

数学,自然想到组合数,逆元,阶乘 先来一发组合数相关, #define MAXN 200001 const int mod=1000000007; typedef long long ll; int n,m,r,c; ll ans,s; ll inv[MAXN],fac[MAXN],dev[MAXN]; //inv[]逆元,fac[]阶乘,dev[]阶乘的逆元 void chuli(int x) { inv[1]=1; fac[1]=1; dev[1]=1; fac[0]=1; dev[0]=1

有关位运算的题

位运算 与& 0&0=0 1&0=0 0&1=0 1&1=1 或| 0|0=0 1|0=1 0|1=1 1|1=1 异或^ 0^0=0 1^0=1 0^1=1 1^1=0 题目: 实现一个函数,输入一个整数,输出该数的二进制表示中1的个数,例如9的二进制是1001,有两个1,输入9,输出1 程序1.0 写法1:模除法 int CountOne(int n) { int count = 0; while (n) { int ret = 0; ret = n % 2;

一道位运算技巧题

今天Mayuyu遇到一个非常有意思的题目,描述如下 题目:有一堆数,若干个数出现了3次,只有一个数出现了1次,找出只出现1次的那个数. 分析:把这个问题进行推广,得到如下描述 有一堆数,除了一个元素出现次外,其它每个数都出现了次,现在需要找出出现次的这个数. 代码: #include <bits/stdc++.h> using namespace std; const int N = 10005; int a[N]; int singleNumber(int a[], int n, int p

关于位运算的水题

找数字2 Time Limit: 25000ms, Special Time Limit:50000ms, Memory Limit:32768KB Total submit users: 92, Accepted users: 67 Problem 11466 : No special judgement Problem description 给定2n+1个数字,只有一个数字出现了奇数次,其余的数字都出现了偶数次,现在你需要找出出现奇数次的数字. Input 包含多组数据,每组数据第一行为一

bzoj5108 [CodePlus2017]可做题 位运算dp+离散

[CodePlus2017]可做题 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 87  Solved: 63[Submit][Status][Discuss] Description qmqmqm希望给sublinekelzrip出一道可做题.于是他想到了这么一道题目:给一个长度为n的非负整数序列ai,你需 要计算其异或前缀和bi,满足条件b1=a1,bi=bi?1 xor ai(i≥2).但是由于数据生成器出现了问题,他生成的序列a 的长度特

LeetCode刷题总结-双指针、位运算和分治法篇

本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. 独特字符串,难度困难 题号:923. 三数之和的多种可能,难度中等 2.实际场景应用问题 题号:826. 安排工作以达到最大收益,难度中等 3.元素对问题 题号:986. 区间列表的交集,难度中等 二.位运算 1.字符串和数组问题 题号:137. 只出现一次的数字 II,难度中等 题号:318.

HDU1196_Lowest Bit【位运算】【水题】

Lowest Bit Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8043    Accepted Submission(s): 5920 Problem Description Given an positive integer A (1 <= A <= 100), output the lowest bit of A. For

刷题向》一道关于位运算的神题(BZOJ3668)(HARD)

个人觉得这道题对于位运算的加深理解很有意义 根据题目所说,我们要求出一个在给定范围里的自变量,使得最终结果最大. 那么因为这道题是针对于位运算的,所以可以想到用对于位运算取极限情况,即对于"0"和"(2^bit)-1"这两种情况判断,然后即可以得到每一位在这几种操作之后的所有情况,然后根据合适的情况反推得到满足条件的最优解,然后就能A啦 直接甩题目&代码 Description 21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后

【NOIP模拟题】“与”(位运算)

因为是与运算,所以我们可以贪心地每次找最高位的,将他们加入到新的序列中,然后每一次在这个新的序列继续找下一个位. 然后最后序列中任意两个的与运算的值都是一样的且是最大的. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue&g