【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

第 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 <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <ctime>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <set>
  8 #include <vector>
  9 #include <queue>
 10 #include <typeinfo>
 11 #include <map>
 12 #include <stack>
 13 typedef long long ll;
 14 using namespace std;
 15 inline ll read()
 16 {
 17     ll x=0,f=1;
 18     char ch=getchar();
 19     while(ch<‘0‘||ch>‘9‘)
 20     {
 21         if(ch==‘-‘)f=-1;
 22         ch=getchar();
 23     }
 24     while(ch>=‘0‘&&ch<=‘9‘)
 25     {
 26         x=x*10+ch-‘0‘;
 27         ch=getchar();
 28     }
 29     return x*f;
 30 }
 31 //**************************************************************************************
 32 struct ss
 33 {
 34     int l,r,v;
 35     bool lazy;
 36 }tr[100000*5];
 37 int n,m;
 38 void build(int k,int s,int t)
 39 {
 40     tr[k].l=s;
 41     tr[k].r=t;
 42     if(s==t){
 43         return ;
 44     }
 45     int mid=(s+t)>>1;
 46     build(k<<1,s,mid);
 47     build(k<<1|1,mid+1,t);
 48 }
 49 void pushdown(int k)//设置好
 50 {
 51     if(!tr[k].lazy)return;
 52     tr[k<<1].lazy=!tr[k<<1].lazy;
 53     tr[k<<1|1].lazy=!tr[k<<1|1].lazy;
 54     tr[k<<1].v=tr[k<<1].r-tr[k<<1].l+1-tr[k<<1].v;
 55     tr[k<<1|1].v=tr[k<<1|1].r-tr[k<<1|1].l+1-tr[k<<1|1].v;
 56     tr[k].lazy=0;
 57 }
 58 void update(int k,int s,int t)
 59 {
 60     pushdown(k);
 61     if(tr[k].l==s&&tr[k].r==t)
 62     {
 63        tr[k].v=tr[k].r-tr[k].l+1-tr[k].v;
 64        if(tr[k].l!=tr[k].r) tr[k].lazy=1;//!!!!!!!
 65         return;
 66     }
 67     int mid=(tr[k].l+tr[k].r)>>1;
 68     if(t<=mid)update(k<<1,s,t);
 69     else if(s>mid)update(k<<1|1,s,t);
 70     else
 71     {
 72         update(k<<1,s,mid);
 73         update(k<<1|1,mid+1,t);
 74     }
 75     tr[k].v=tr[k<<1].v+tr[k<<1|1].v;
 76 }
 77 int ask(int k,int s,int t)
 78 {
 79     pushdown(k);
 80     if(s==tr[k].l&&tr[k].r==t)
 81     {
 82         return tr[k].v;
 83     }
 84     int mid=(tr[k].l+tr[k].r)>>1;
 85     if(t<=mid)  return ask(k<<1,s,t);
 86     else if(s>mid)return ask(k<<1|1,s,t);
 87     else{
 88         return ask(k<<1,s,mid)+ask(k<<1|1,mid+1,t);
 89     }
 90 }
 91 int main()
 92 {
 93
 94     scanf("%d%d",&n,&m);
 95     build(1,1,n);
 96     for(int i=1;i<=m;i++)
 97     {
 98         int t,x,y;
 99         scanf("%d%d%d",&t,&x,&y);
100         if(t==0)
101         {
102             update(1,x,y);
103         }
104         else printf("%d\n",ask(1,x,y));
105     }
106     return 0;
107 }
时间: 2024-12-17 22:37:43

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

Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)

Finally the Great Magical Lamp was in Aladdin's hand. Now he wanted to return home. But he didn't want to take any help from the Genie because he thought that it might be another adventure for him. All he remembered was the paths he had taken to reac

树链剖分+线段树 单点修改 区间求和 模板

马上要去西安打邀请赛了,存下板子 首先是vector存图的: #include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 const int M = 2e5+10; int fa[M],dep[M],siz[M],son[M

Spoj 1716 Can you answer these queries III 线段树 单点修改 区间求最大子段和

题目链接:点击打开链接 == 原来写1的时候已经把更新函数写好了.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lso

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

非递归线段树区间修改区间求和的两种实现(以POJ 3468为例)

题意:就是一个数列,支持  查询区间和  以及  区间内的数都加上 C . 递归线段树很好写,就不讲了. 递归版本        : 内存:6500K   时间:2.6 秒 非递归版本一: 内存:4272K   时间:1.1秒 非递归版本二: 内存:4272K   时间:1.3秒 -------------------------------------------------------------------------------------------------------------

POJ 3468 A Simple Problem with Integers(线段树模板之区间增减更新 区间求和查询)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 140120   Accepted: 43425 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o

HDOJ--4893--Wow! Such Sequence!【线段树+单点、区间更新】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:给你一个长度n的数列,初始都为0,有三种操作,第一种给第k个位置的数加d,第二种是查询区间 [l , r] 的总和,第三种是使区间 [l , r] 的值改为离它最近的那个斐波那契数的值. 我刚开始用sum数组存储节点的值,第三种操作是个区间更新,但是区间更新的值不一样,我就想当然的搜到最底部的节点来处理更新,果断T了.后来想了想,其实可以在节点上再加一个信息,就是这个值下次进行第三种操作要变

线段树2 求区间最小值

线段树2 求区间最小值 从数组arr[0...n-1]中查找某个数组某个区间内的最小值,其中数组大小固定,但是数组中的元素的值可以随时更新. 数组[2, 5, 1, 4, 9, 3]可以构造如下的二叉树(背景为白色表示叶子节点,非叶子节点的值是其对应数组区间内的最小值,例如根节点表示数组区间arr[0...5]内的最小值是1): 线段树的四种操作: 1.线段树的创建 2.线段树的查询 3.线段树的更新单节点 4.线段树的更新区间 直接上完整代码吧 1 #include <bits/stdc++.

UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)

题目链接:http://acm.upc.edu.cn/problem.php?id=2224 题意:给出n个数pi,和m个查询,每个查询给出l,r,a,b,让你求在区间l~r之间的pi的个数(A<=pi<=B,l<=i<=r). 参考链接:http://www.cnblogs.com/zj62/p/3558967.html #include <iostream> #include <cstdio> #include <cstring> #incl

hdu - 4973 - A simple simulation problem.(线段树单点更新 + 区间更新)

题意:初始序列 1, 2, ..., n,m次操作(1 <= n,m<= 50000),每次操作可为: D l r,将区间[l, r]中的所有数复制一次: Q l r,输出区间[l, r]中同一数字个数的最大值. (0 <= r – l <= 10^8, 1 <= l, r <= 序列元素个数) 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4973 -->>因为区间内数字是依次递增的,所以可以以数字为叶建线段