codevs1690 开关灯

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;
}
时间: 2024-10-14 18:23:46

codevs1690 开关灯的相关文章

codevs1690开关灯

#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #define maxn 100010 using namespace std; int n,m,num; struct node { int lc,rc; int l,r; int sum,bj; }t[maxn*2+100]; void Build(int ll,int rr) { int k=++num; t[

CODEVS1690|开关灯|线段树(带lazy)

题目描述 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 行: 每行表示一个操作, 有三个用空格分开的整数

CODEVS线段树小结

CODEVS1369 xth 砍树 题目大意:区间查询和,单点修改区间中点. 思路:比较简单的线段树,可是在double和float上栽了跟头,以后统一用double,输出printf里面用f,不要用llf(我zuo). #include<iostream> #include<cstdio> using namespace std; int tree[800000]={0},a[200001]={0}; void build(int i,int l,int r) { int mid

【codevs1690】开关灯 线段树 区间修改+区间求和(标记)

[codevs1690]开关灯 2014年2月15日4930 题目描述 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 第

【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代表询问状态)

【codevs1690】开关灯【线段树】

题目描述 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 行: 每行表示一个操作, 有三个用空格分开的整数

bzoj1230 [Usaco2008 Nov]lites 开关灯

1230: [Usaco2008 Nov]lites 开关灯 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1615  Solved: 847[Submit][Status][Discuss] Description Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每一头被连续的编号为1..N, 站在一个彩色的灯下面.刚到傍晚的时候

开关灯

问题: 开灯问题,有n盏灯,编号为1~n.第一个人把所有灯都打开,第二个人按下所有编号为2的倍数的开关(这些灯将被关掉),第三个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),以此类推.一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号.(k<n<1000) 分析: 用数组来存储灯的状态,判断灯是否开着. 代码: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <s

1230: [Usaco2008 Nov]lites 开关灯

1230: [Usaco2008 Nov]lites 开关灯 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1162  Solved: 589[Submit][Status] Description Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每一头被连续的编号为1..N, 站在一个彩色的灯下面.刚到傍晚的时候, 所有的灯都是关