码迷,mamicode.com
首页 > 其他好文 > 详细

codevs1690 开关灯

时间:2017-06-25 14:55:43      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:hint   ted   一个   code   app   线段   efault   std   简单   

1690 开关灯

 

USACO

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
 
题目描述 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
 
数据范围及提示 Data Size & Hint

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

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

分析:其实是一道比较简单的线段树的题目。我们只需要记录关着的灯的数量和开着的灯的数量,操作时交换即可,涉及到区间操作,需要用到lazy标记,其实如果一个区间操作两次,那么相当于不操作,所以当一个区间的lazy标记为奇数时才往下传.

/*
作者:zbtrs
题目:p1690 开关灯
*/
#include <iostream>  
#include <cstdlib>  
#include <cstdio>  
#include <cstring>  
#include <string>  
#include <algorithm>
#include <queue>
#include <stack>
#include <cmath>

using namespace std;

int n, m,d1[500010],add[500010],d2[500010];

void pushup(int o)
{
    d1[o] = d1[o * 2] + d1[o * 2 + 1]; //
    d2[o] = d2[o * 2] + d2[o * 2 + 1]; //
}

void pushdown(int o, int l, int r)
{
    if (add[o] % 2 == 1)
    {
        add[o * 2] += add[o];
        add[o * 2 + 1] += add[o];
        add[o] = 0;
        swap(d1[o * 2], d2[o * 2]);
        swap(d1[o * 2 + 1], d2[o * 2 + 1]);
    }
}

void build(int o, int l, int r)
{
    if (l == r)
    {
        d1[o] = r - l + 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(o * 2, l, mid);
    build(o * 2 + 1, mid + 1, r);
    pushup(o);
}

void update(int o, int l, int r, int x, int y)
{
    if (x <= l && r <= y)
    {
        swap(d1[o], d2[o]);
        add[o]++;
        return;
    }
    pushdown(o, l, r);
    int mid = (l + r) >> 1;
    if (x <= mid)
        update(o * 2, l, mid, x, y);
    if (y > mid)
        update(o * 2 + 1, mid + 1, r, x, y);
    pushup(o);
}

int query(int o, int l, int r, int x, int y)
{
    if (x <= l && r <= y)
        return d2[o];
    pushdown(o, l, r);
    int mid = (l + r) >> 1,cnt = 0;
    if (x <= mid)
        cnt += query(o * 2, l, mid, x, y);
    if (y > mid)
        cnt += query(o * 2 + 1, mid + 1, r, x, y);
    pushup(o);
    return cnt;
}

int main()
{
    scanf("%d%d", &n, &m);
    build(1, 1, n);
    for (int i = 1; i <= m; i++)
    {
        int id, x, y;
        scanf("%d%d%d", &id, &x, &y);
        if (id == 0)
            update(1, 1, n, x, y);
        if (id == 1)
            printf("%d\n", query(1, 1, n, x, y));
    }

    return 0;
}

 

codevs1690 开关灯

标签:hint   ted   一个   code   app   线段   efault   std   简单   

原文地址:http://www.cnblogs.com/zbtrs/p/7076714.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!