【codevs1690】开关灯【线段树】
2015-05-14 15:16
411 查看
题目描述 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表示,灯灭用0表示
线段树保存区间和。
一个区间取反后亮着灯的个数实际上是r-l+1-t[x];
我们在下放标记时只需要lazy[x]=!lazy[x]。
代码:
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表示,灯灭用0表示
线段树保存区间和。
一个区间取反后亮着灯的个数实际上是r-l+1-t[x];
我们在下放标记时只需要lazy[x]=!lazy[x]。
代码:
[code]#include<iostream> #include<cstdio> using namespace std; int t[1000001],n,m,kind,x,y,lazy[1000001]; void paint(int k,int l,int r) { t[k]=r-l+1-t[k]; lazy[k]=!lazy[k]; } void pushdown(int k,int l,int r) { int mid; mid=(l+r)/2; paint(k*2,l,mid); paint(k*2+1,mid+1,r); lazy[k]=0; } void insert(int k,int l,int r,int ll,int rr) { int mid; if (ll<=l&&r<=rr) { paint(k,l,r); return; } mid=(l+r)/2; if (lazy[k]==1) pushdown(k,l,r); if (ll<=mid) insert(k*2,l,mid,ll,rr); if (mid<rr) insert(k*2+1,mid+1,r,ll,rr); t[k]=t[2*k]+t[2*k+1]; } int qsum(int k,int l,int r,int ll,int rr) { int mid,ans(0); if (ll<=l&&r<=rr) return t[k]; mid=(l+r)/2; if (lazy[k]==1) pushdown(k,l,r); if (ll<=mid) ans+=qsum(k*2,l,mid,ll,rr); if (mid<rr) ans+=qsum(k*2+1,mid+1,r,ll,rr); return ans; } int main() { cin>>n>>m; for (int i=1;i<=m;i++) { scanf("%d%d%d",&kind,&x,&y); if (kind==0) insert(1,1,n,x,y); if (kind==1) printf("%d\n",qsum(1,1,n,x,y)); } }
相关文章推荐
- codevs 1690 开关灯 线段树 解题报告
- 【codevs1690】开关灯 线段树 区间修改+区间求和(标记)
- Codevs 题目1690 开关灯(线段树区间异或)
- codevs 1690 开关灯 线段树
- CodeVS1690 开关灯 解题报告【数据结构】【线段树】
- codevs1690 开关灯(线段树)
- codevs 1690 开关灯 线段树水题
- 【codevs1690】开关灯 线段树
- Codevs_1690_开关灯_(线段树)
- 线段树--codevs 1690 开关灯
- 【codevs1690】开关灯,线段树练习
- 【CodeVS1690】开关灯
- codevs 1690 开关灯
- codevs1690开关灯
- Code[VS]1690 开关灯 题解
- codevs 1690 开关灯
- codevs1690 开关灯
- AC日记——开关灯 codevs 1690
- 【codevs 1080】线段树练习
- CODEVS(WIKIOI) 2018 反病毒软件(线段树)