fjwc2019 D3T1 签到题 (贪心)

#184. 「2019冬令营提高组」签到题

每次询问接近O(1).......考虑贪心

怎么贪心呢?

对于相邻的两个数,我们要保证异或x后单调不降

我们找到两个数二进制上最高的相异位

当左边的数相异位为0,右边为1时,显然x的该位只能为0,否则异或后不符条件。

当左边的数相异位为1,右边为0时,x的该位就必须为1,也就是必须异或一次改变大小关系。

对于剩下的位......取0就行辣

当某位既要取1又要取0,显然就是不符合条件,就是无解了

每次修改的时候把上一位的数据清掉就得了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void read(int &x){
    char c=getchar();x=0;
    while(c<'0'||c>'9') c=getchar();
    while('0'<=c&&c<='9') x=x*10+(c^48),c=getchar();
}
int n,m,a[1000005],c[33][2];
void add(int id,int k){
    if(id==n||id==0) return;
    if(a[id]==a[id+1]) return ;//重要剪枝
    int i=30;
    while(((a[id]>>i)&1)==((a[id+1]>>i)&1)) --i;//找到最高相异位
    c[i][((a[id]>>i)&1)]+=k;
}
int calc(){
    int re=0;
    for(int i=0;i<=30;++i){
        if(c[i][1]){
            if(c[i][0]) return -1;
            re+=1<<i;
        }
    }return re;
}
int main(){
    freopen("sort.in","r",stdin);
    freopen("sort.out","w",stdout);
    read(n); int q1,q2;
    for(int i=1;i<=n;++i) read(a[i]);
    for(int i=1;i<n;++i) add(i,1);
    printf("%d\n",calc());
    read(m);
    while(m--){
        read(q1);read(q2);
        add(q1,-1); add(q1-1,-1);//把上一位的信息清除掉
        a[q1]=q2;
        add(q1,1); add(q1-1,1);
        printf("%d\n",calc());
    }return 0;
}

 

转载于:https://www.cnblogs.com/kafuuchino/p/10468485.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值