noip膜你赛day2第一题

题意:

有一个由0和1组成的数组,定义一种新运算azui,1 azui 1 = 1,1 azui 0 = 0,0 azui 1 = 0,0 azui 0 = 1,给出一个长度为n的该数组,以及m个查询l,r,表示将区间[l,r]从l一个一个azui到r的值。

题解:

额,先说说稍微复杂一点的做法,可以发现,这个azui运算是满足结合律的,于是你就可以用线段树来做了

但其实,有更简单的方法,数数0的个数就可以了,奇数为0,偶数为1,代码附上我考试时的心路历程,里面有证明

code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>

const int MAXN=1000005;
using namespace std;
int n,m,l,r,sum[MAXN];
bool a[MAXN];

inline void Read(int &Ret){
    char ch;bool flag=0;
    for(;ch=getchar(),ch<'0'||ch>'9';)if(ch=='-')flag=1;
    for(Ret=ch-'0';ch=getchar(),'0'<=ch&&ch<='9';Ret=Ret*10+ch-'0');
    flag&&(Ret=-Ret);
}
inline void Read(bool &Ret){
    char ch;bool flag=0;
    for(;ch=getchar(),ch<'0'||ch>'9';)if(ch=='-')flag=1;
    for(Ret=ch-'0';ch=getchar(),'0'<=ch&&ch<='9';Ret=Ret*10+ch-'0');
    flag&&(Ret=-Ret);
}
int main()
{
    //freopen("azui.in","r",stdin);
    //freopen("azui.out","w",stdout);
    Read(n);
    for(int i=1;i<=n;i++)
    {
        Read(a[i]);
        sum[i]=sum[i-1];
        if(!a[i]) sum[i]++;
    }
    Read(m);
    for(int i=1;i<=m;i++)
    {
        Read(l); Read(r);
        int cnt=sum[r]-sum[l-1];
        if(cnt&1) putchar('0');
        else putchar('1');
        putchar(10);
    }
}
/*
5
1 0 1 0 1
5
2 3
3 4
4 5
1 3
1 4

print 0 0 0 0 1

灯泡状态相同为1,相异为0
0 azui 0 = 1
0 azui 0 azui 1 = 0 azui 1 azui 0 = 1 azui 0 azui 0 = 1;满足交换律
0 azui 0 azui 0 = 0; 1 azui 1 azui 1 = 1;满足交换律
1 azui 1 azui 0 = 1 azui 0 azui 1 = 0 azui 1 azui 1 = 0;满足交换律
要是真的满足交换律,就简单了
验证一下,暴力嘛,嘿嘿。
1 0 1 1 0 1 0 0 0 1
5个1,5个0,最后结果应该是1
  0 0 0 1 1 0 1 0 0
其实最后结果为0
看来是不满足交换律了
要是当前ans为1,那么遇到0,ans便会为0
要是当前ans为0,那么遇到0,ans便会为1!!!这两句话就是证明,可以发现1并不会影响结果
那么要是我开一个数组,a[i]储存左边和右
边第一个状态为0的数呢?
我记得用map是可以nlogn求的吧
map<int,int> M;
for(int i=1;i<=n;i++)
{
    int t=-1;
    if(M.count(0))
        t=M[!a[i]];
    M[a[i]]=i;
    left[a[i]]=t;
}
那么这就是说,1是不会影响结果的,
影响结果的只会是0?
哈哈哈哈,找到规律了
1 0 0 ans=1
0 0 0
1 1 0 0
1 0 0 0
那么开始ans的值会不会有影响?
若是开始ans为1,那么有奇数个0,ans=0
若是开始ans为0,那么有奇数个0,ans=1
但是事实上,ans开始为0,则意味着有偶数个0
所以说只需要判断0的个数即可
*/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值