[BZOJ3378]一套NOIP膜你题:膜拜azui

17 篇文章 0 订阅
9 篇文章 0 订阅
【问题描述】

一天,小 A 给了 J·G 一道水题,J·G 一眼秒了,现在 J·G 想考考你们:小 A 个灯,排成了一列,现在小给出来一个叫做 azui 的奇葩操作,我们把开着的灯看作数字 1,把关着的灯看作数字 0,定义0 azui 0 = 1,0 azui 1 = 0,1 azui 1 = 1, 1 azui 0 = 0。现在小 A 有 N 个问题azui(l,r),表示询问从左往右的第 l 个灯向右一个一个 azui 到第 r 个灯的结果是什么。


【输入】
第 1 行一个整数 N 表示序列的长度。
第 2 行 N 个整数 Ai,每个数不是 0 就是 1,表示灯是关的还是开的。
第 3 行一个整数 M 表示询问的个数。

第 4~M+3 行,每行两个整数 l 和 r,表示询问 azui(l,r)。


【输出】

共 M 行,第 i 行回答第个询问。


【样例输入】
5
1 0 1 0 1
5
2 3
3 4
4 5
1 3

1 4


【数据范围】
对于 30%的数据,N  M <= 5000
对于 80%的数据,N  M <= 500000

对于 100%的数据,N  M <= 1000000



题解:找规律

一段区间的值只与其中0的个数有关,偶数个0为1,奇数个0为0。


#include<iostream> 
#include<cstring> 
#include<cstdio> 
#include<cstdlib> 
#include<cmath> 
#include<algorithm> 
using namespace std; 
const int N=1e6+10; 
int n, m, sum[N], l, r; 
char s[N];

void Getin(int &shu){
	char c;int f=1;shu=0;
	for(c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
	for(;c>='0'&&c<='9';c=getchar()) shu=shu*10+c-'0';
	shu*=f;
}
  
int main() { 
    Getin(n); 
    for( int i=1; i<=n; i++ )
        Getin(sum[i]), sum[i]+=sum[i-1];
    scanf( "%d", &m ); 
    for( int i=1; i<=m; i++ ) { 
        Getin(l); Getin(r); 
        if( ( l-r+1-sum[r]+sum[l-1] )&1 ) printf( "0\n" ); 
        else printf( "1\n" ); 
    } 
    return 0; 
}


也可以用线段树,但对于人品不好的人,线段树会T掉

#include<iostream>  
#include<cstring>  
#include<cstdio>  
#include<cstdlib>  
#include<cmath>  
#include<algorithm>  
using namespace std;  
const int N=1e6+10;  
int n, m, l, r;  
struct node{ int l, r, num; }tree[N<<2];  
  
void Getin(int &shu){ 
    char c;int f=1;shu=0; 
    for(c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') f=-1; 
    for(;c>='0'&&c<='9';c=getchar()) shu=shu*10+c-'0'; 
    shu*=f; 
} 
  
int Azui( int a, int b ) { return ( a^b )^1; }  
    
void Build( int l, int r, int pos ) {  
    tree[pos].l=l; tree[pos].r=r;  
    if( l==r ) {  
        Getin(tree[pos].num);  
        return;  
    }  
    int mid=( l+r )>>1;  
    Build( l, mid, pos<<1 );  
    Build( mid+1, r, pos<<1|1 );  
    tree[pos].num=Azui( tree[pos<<1].num, tree[pos<<1|1].num );  
}  
    
int Find( int l, int r, int pos ) {  
    if( tree[pos].r<l || r<tree[pos].l ) return -1;  
    if( l<=tree[pos].l && tree[pos].r<=r ) return tree[pos].num;  
      
    int numl=Find( l, r, pos<<1 );  
    int numr=Find( l, r, pos<<1|1 );  
      
    if( numl!=-1 && numr!=-1 ) return Azui( numl, numr );  
    if( numl==-1 && numr==-1 ) return -1;  
    if( numl!=-1 ) return numl;  
    else return numr;  
}  
    
int main() {  
    Getin(n); getchar();  
    Build( 1, n, 1 );  
    scanf( "%d", &m );  
    for( int i=1; i<=m; i++ ) {  
        Getin(l); Getin(r);  
        printf( "%d\n", Find( l, r, 1 ) );  
    }  
    return 0;  
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值