Code[VS]1690 开关灯 题解

Code[VS]1690 开关灯 题解 

时间限制: 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

——————————————————————————————————————————————

分析:

本题最暴力的思路,是用数组模拟区间开关灯的操作,但是数据量较大,暴力思路会超时。这时考虑使用带延迟标记的线段树。这道题属于比较明显的线段树题。

以下代码:

(代码比较长^_^)

  1 #include "bits/stdc++.h"
  2
  3 #define maxN 100010
  4
  5 using namespace std;
  6 typedef long long QAQ;
  7
  8 struct Tree
  9 {
 10     int l, r ;
 11     QAQ sum ;//当前开着的灯数量
 12     bool idv;//开关灯的延迟标记
 13 };
 14
 15 QAQ Min(QAQ a, QAQ b)
 16 {
 17     return a > b ? b : a;
 18 }
 19
 20 Tree tr[maxN << 2];
 21
 22 void Push_down ( int i , int m)
 23 {
 24     if(tr[i].idv)//当前结点有延迟标记
 25     {
 26         tr[i << 1].idv = !tr[i << 1].idv ;//左
 27         tr[i << 1 | 1].idv = !tr[i << 1 | 1].idv ;//右
 28         tr[i << 1].sum = tr[i << 1].r - tr[i << 1].l + 1 - tr[i << 1].sum ;//所以灯开关状态取反
 29         tr[i << 1 | 1].sum = tr[i << 1 | 1].r - tr[i << 1 | 1].l + 1 - tr[i << 1 | 1].sum ;//同上
 30         tr[i].idv = !tr[i].idv ;//清零!!!
 31     }
 32 }
 33
 34 void Build_Tree (int x , int y, int i)
 35 {
 36     tr[i].l = x ;//左端点
 37     tr[i].r = y ;//右端点
 38     if( x == y)return ;
 39     else
 40     {
 41         QAQ mid = (tr[i].l + tr[i].r ) >> 1 ;
 42         Build_Tree ( x , mid , i << 1);//左递归
 43         Build_Tree (mid + 1 , y , i << 1 | 1);//右递归
 44     }
 45 }
 46
 47 void Update_Tree (int q , int w , int i)
 48 {
 49     if( w >= tr[i].r && q <= tr[i].l)//被完全包含
 50     {
 51         tr[i].idv = !tr[i].idv;//延迟标记
 52         QAQ tot = tr[i].r - tr[i].l + 1;//当前结点总共的灯
 53         tr[i].sum = tot - tr[i].sum;//开关状态全部取反
 54         return ;
 55     }
 56     else
 57     {
 58         Push_down( i , tr[i].r - tr[i].l + 1 );//信息下传函数
 59         QAQ mid = (tr[i].l + tr[i].r) >> 1;
 60         if( q > mid )
 61         {
 62             Update_Tree ( q , w , i << 1 | 1);
 63         }
 64         else if ( w <= mid )
 65         {
 66             Update_Tree ( q , w , i << 1);
 67         }
 68         else
 69         {
 70             Update_Tree ( q , w , i << 1 | 1);
 71             Update_Tree ( q , w , i << 1);
 72         }
 73         tr[i].sum = tr[i << 1].sum + tr[i << 1 | 1].sum ;//回溯更新
 74     }
 75 }
 76
 77 QAQ Query_Tree (int q , int w , int i )
 78 {
 79     if( w >= tr[i].r && q <= tr[i].l)
 80     {
 81         return tr[i].sum;//被完全包含直接返回值
 82     }
 83     else
 84     {
 85         Push_down( i , tr[i].r - tr[i].l + 1 );
 86         QAQ mid = (tr[i].l + tr[i].r ) >> 1;
 87         if( q > mid )
 88         {
 89             return Query_Tree ( q , w , i << 1 | 1);
 90         }
 91         else if ( w <= mid )
 92         {
 93             return Query_Tree ( q , w , i << 1);
 94         }
 95         else
 96         {
 97             return Query_Tree ( q , w , i << 1 | 1) + Query_Tree ( q , w , i << 1);
 98         }
 99     }
100 }
101
102 int main ( )
103 {
104     QAQ N, M;
105     int op, l, r;
106     scanf("%d%d", &N, &M);
107     Build_Tree ( 1 , N , 1 );//建树操作
108     while (M--)
109     {
110         scanf("%d", &op);
111         if( !op )
112         {
113             scanf("%d%d", &l, &r);
114             Update_Tree ( l , r , 1 );//更新树
115         }
116         else
117         {
118             scanf("%d%d", &l, &r);
119             printf("%lld\n", Query_Tree ( l , r , 1 ));//查询
120         }
121     }
122     return 0 ;
123 }

( 完 )

时间: 2024-08-08 05:18:47

Code[VS]1690 开关灯 题解的相关文章

1690 开关灯

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 Desc

线段树--codevs 1690 开关灯

codevs 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

Code[VS] 1022 覆盖 题解

Code[VS] 1022 覆盖 题解 Hungary Algorithm 题目传送门:Code[VS] 1022 题目描述 Description 有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地.如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积. 输入描述 Input Description 输入文件的第一行是两个整数N,M  (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表

线段树——codevs 1690 开关灯

先来一发题目: 1690 开关灯 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m<=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1<=i,j,x,y<=N) 输入描述 Input Description 第 1 行: 用空格隔

codevs 1690 开关灯 线段树+延迟标记

1690 开关灯 时间限制: 1 s 空间限制: 128000 KB 题目描述 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和

Code[VS] 2152 滑雪题解

Code[VS] 2152 滑雪题解 题目描述 Description trs喜欢滑雪.他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形.为了得到更快的速度,滑行的路线必须向下倾斜.例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一.例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条. 输入描述 Input Description 输入文件 第1行: 两个数字r,c(1<=r,c<=100),表示矩阵的行列.第

Code[VS] 2370 LCA 题解

Code[VS] 2370 小机房的树 题解 LCA 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力.已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力 输入描述 I

CodeVs 1690 开关灯

线段树区间更新 区间查询~好久没写过线段树了 写挫了好几次了了了..最后瞅了瞅题解才发现自己思路有些问题 #include <cstdio> #include <algorithm> using namespace std;   #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1   int n,m; struct data{     int l,r,v;     bool lazy; }tr[2000001]

LOJ6354 &amp; 洛谷4366:[Code+#4]最短路——题解

https://loj.ac/problem/6354 https://www.luogu.org/problemnew/show/P4366 题面见上面. 这题很妙,且可能是我傻,感觉这题不太好想. 前45pts很好骗就不说了. 朴素的建法是O(n^2+m)的,一个点都过不了. 然而事实上一个从x->y权值为w的边是可以被其他边取代的,我们可以把x拆成二进制,一位一位的修改最终到达y,此时经过的权值显然也是w. 也就是说,对于一个点x,我们只需要让他和x*2^k连边即可,这样就优化为O(nlo