codevs 1690 开关灯 线段树

题目描述 Description
YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N)

输入描述 Input Description
第 1 行: 用空格隔开的两个整数N和M
第 2..M+1 行: 每行表示一个操作, 有三个用空格分开的整数: 指令号(0代表按下开关,1代表询问状态), x 和 y
输出描述 Output Description
第 1..询问总次数 行:对于每一次询问,输出询问的结果

样例输入 Sample Input
4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4

样例输出 Sample Output
1
2

分析:这题是典型的区间修改区间查询,但有一个特别的地方,就是偶数关灯,奇数开灯,所以只有在lazy为奇数时才会放下更新答案,所以特判一下。

# include <iostream>
# include <cstdio>
# include <cmath>
# include <list>
# include <cstring>
# include <map>
# include <ctime>
# include <algorithm>
# include <queue>
using namespace std;
typedef long long ll;
ll read(){
    register ll f=1,i=0;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
    return f*i;
}
int tr[1000001],n,m,k,x,y,lazy[1000001];
void change(int k,int l,int r)
{
    tr[k]=r-l+1-tr[k];
    lazy[k]=!lazy[k];
}
void push_down(int k,int l,int r)
{
    int mid=(l+r)>>1;
    change(k*2,l,mid);
    change(k*2+1,mid+1,r);
    lazy[k]=0;
}
void updatra(int k,int l,int r,int ll,int rr)
{
    if (ll<=l&&r<=rr)
     {
        change(k,l,r);
        return;
     }
     int mid=(l+r)>>1;
     if (lazy[k]) push_down(k,l,r);
     if (ll<=mid) updatra(k*2,l,mid,ll,rr);
     if (mid<rr) updatra(k*2+1,mid+1,r,ll,rr);
     tr[k]=tr[2*k]+tr[2*k+1];
}
int query(int k,int l,int r,int ll,int rr)
{
    if(ll<=l&&r<=rr) return tr[k];
    int mid=(l+r)>>1,ans=0;
    if(lazy[k]) push_down(k,l,r);
    if(ll<=mid) ans+=query(k*2,l,mid,ll,rr);
    if(mid<rr) ans+=query(k*2+1,mid+1,r,ll,rr);
    return ans;
}
int main()
{

    n=read(),m=read();
    for (int i=1;i<=m;i++)
      {
          k=read(),x=read(),y=read();
          if (k==0) updatra(1,1,n,x,y);
          if (k==1) printf("%d\n",query(1,1,n,x,y));
      }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值