您的位置:首页 > 理论基础 > 数据结构算法

CodeVS1690 开关灯 解题报告【数据结构】【线段树】

2017-08-27 20:06 453 查看
题目描述 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

解题报告

这道题的操作就区间取反+区间求和,用线段树实现。线段树的每一个点存储这段的和以及懒标记。其中懒标记的更新是nd->flag=!nd->flag(取反),而每一次求和应该是这段区间的长度减去原来的和(nd->sum=(rg-lf+1)-nd->sum)。

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000;
int n,m;
int a[N+5];
struct node
{
int sum,flag;
node *lson,*rson;
void pushdown(int lf,int rg)
{
if(flag)
{
int mid=(lf+rg)>>1;
lson->flag=!lson->flag;
lson->sum=(mid-lf+1)-lson->sum;
rson->flag=!rson->flag;
rson->sum=(rg-mid)-rson->sum;
flag=0;
}
}
void update()
{
sum=lson->sum+rson->sum;
}
};
struct node dizhi[4*N+5],*tail=dizhi,*root;
node *build(int lf,int rg)
{
node *nd=++tail;
if(lf==rg)
{
nd->sum=0;
nd->flag=0;
}
else
{
int mid=(lf+rg)>>1;
nd->lson=build(lf,mid);
nd->rson=build(mid+1,rg);
nd->sum=nd->lson->sum+nd->rson->sum;
nd->flag=0;
}
return nd;
}
void modify(node *nd,int lf,int rg,int L,int R)
{
if(L<=lf&&rg<=R)
{
nd->sum=(rg-lf+1)-nd->sum;
nd->flag=!nd->flag;
return ;
}
nd->pushdown(lf,rg);
int mid=(lf+rg)>>1;
if(L<=mid)modify(nd->lson,lf,mid,L,R);
if(R>mid)modify(nd->rson,mid+1,rg,L,R);
nd->update();
}
int query(node *nd,int lf,int rg,int L,int R)
{
if(L<=lf&&rg<=R)return nd->sum;
int mid=(lf+rg)>>1;
nd->pushdown(lf,rg);
long long rt=0;
if(L<=mid)rt+=query(nd->lson,lf,mid,L,R);
if(R>mid)rt+=query(nd->rson,mid+1,rg,L,R);
nd->update();
return rt;
}
int main()
{
scanf("%d%d",&n,&m);
root=build(1,n);
while(m--)
{
int opt,lf,rg;
scanf("%d%d%d",&opt,&lf,&rg);
if(!opt)modify(root,1,n,lf,rg);
else printf("%d\n",query(root,1,n,lf,rg));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: