【CodeVS1690】开关灯

Description

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

Input

第 1 行: 用空格隔开的两个整数N和M
第 2..M+1 行: 每行表示一个操作, 有三个用空格分开的整数: 指令号(0代表按下开关,1代表询问状态), x 和 y 

Output

第 1..询问总次数 行:对于每一次询问,输出询问的结果

Sample Input

4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4

Sample Output

1
2
 

HINT

一共4盏灯,5个操作,下面是每次操作的状态(X代表关上的,O代表开着的):

XXXX -> OOXX -> OXOO -> 询问1~3 -> OOXX -> 询问1~4

题解

线段树,区间改变状态=区间大小-区间和

#include<iostream>
#include<cstdio>
#define N 100010
using namespace std;
struct tree
{
    int L,R;
    int lc,rc;
    int sum,bj;
}t[N*4];
int cur,tot;
void build(int l,int r)
{
    int cur = ++tot;//.....
//    int k = cur;
    t[cur].L=l; t[cur].R=r;
    if (r!=l+1)
    {
        t[cur].lc = tot+1;
        build(l,(l+r)/2);
        t[cur].rc = tot+1; //
        build((l+r)/2,r); //
        t[cur].sum=t[t[cur].lc].sum+t[t[cur].rc].sum; //
    } else t[cur].sum=0; //
}
void updata(int k)
{
    t[t[k].lc].bj+=1; t[t[k].rc].bj+=1;
    t[t[k].lc].sum = t[t[k].lc].R-t[t[k].lc].L-t[t[k].lc].sum;
    t[t[k].rc].sum = t[t[k].rc].R-t[t[k].rc].L-t[t[k].rc].sum;
    t[k].bj = 0;
}
int query(int k,int ll,int rr)
{
    if (t[k].L>=ll && t[k].R<=rr) return t[k].sum;
    if (t[k].bj%2 !=0) updata(k);
    int ans=0;
    int mid = (t[k].L+t[k].R)/2;
    if (ll<mid) ans+=query(t[k].lc,ll,rr);
    if (rr>mid) ans+=query(t[k].rc,ll,rr);
    return ans; 
}
void change (int k,int ll,int rr)
{
    if (t[k].L>=ll && t[k].R<=rr)
    {
        t[k].bj++;
        t[k].sum = t[k].R-t[k].L-t[k].sum;
        return ;
    }
    if (t[k].bj%2 !=0) updata(k);
    int mid = (t[k].L+t[k].R)/2;
/*    if (ll<mid) change(t[k].lc,ll,mid);
    if (rr>mid) change(t[k].rc,mid,rr); 
    不能这样写,因为mid 不一定比rr小!!
    比如说在[1,10) 中修改[2,3)  就把修改范围扩大了!*/
/*    if (ll<mid) change(t[k].lc,ll,(ll+rr)/2); 
    if (rr>mid) change(t[k].rc,(ll+rr)/2,rr); 
    也不能这样写,比如在[1,20)修改[3,5)
    就变成了在[1,10)修改[3,4)
*/
    if (ll<mid) change(t[k].lc,ll,rr);
    if (rr>mid) change(t[k].rc,ll,rr);//所以还是按模板来吧。。。 
    t[k].sum = t[t[k].lc].sum + t[t[k].rc].sum;
}

int main()
{
    int n,m,pd,l,r;
    scanf("%d%d",&n,&m);
    build (1,n+1);
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&pd);
        scanf("%d%d",&l,&r);
        if (pd) 
            printf("%d
",query(1,l,r+1));
        else 
            change(1,l,r+1);
    }
}
原文地址:https://www.cnblogs.com/liumengyue/p/5494576.html