usaco 2008 月赛 lites 开关灯 题解
所有的灯都是关闭的. 奶牛们通过N个按钮来控制灯的开关; 按第i个按钮可以 改变第i个灯的状态.奶牛们执行M (1 <= M <= 100,000)条指令, 每个指令都是两个整数中的一个(0 <= 指令号 <= 1). 第1种指令(用0表示)包含两个数字S_i和E_i (1 <= S_i <= E_i <= N), 它们表示起始开关 和终止开关. 奶牛们只需要把从S_i到E_i之间的按钮都按一次, 就可以完成这个指令. 第2种指令(用1表示)同样包含两个数字S_i和E_i (1 <= S_i <= E_i
<= N), 不过这种指令 是询问从S_i到E_i之间的灯有多少是亮着的. 帮助FJ确保他的奶牛们可以得到正确的答案.
这是我做的第一道线段树的题目,以前只了解过模板——下面我就来介绍一下。
-------------------------------------------线段树的介绍-------------------------------------------------------
线段树是什么?就是一种二叉树结构,而且它的每一个结点代表一条线段的和。
以下是百度百科的详细解释:
一般线段树我都是用堆来储存的,即a[i]的左儿子是a[i*2],右儿子是a[i*2+1]。
线段树快在哪里呢?他对于每个结点的修改和访问都是log(n)的效率。
相信到这里都很好理解,下面介绍一种更加强大的思想:lazy思想。
如果我要将a--b的区间的每一个值都加上p,那么效率就是(b-a+1)log(n)。有没有更快的方法呢?
通过研究,我们发现:如果它只修改而并不访问,我们岂不是不用更新了!
于是我们可以再开一个域cnt,表示目前有多少次累加被积压着。每次处理到k结点时(注意,这个处理包括访问和修改等),我们都把它积压的值给加上,然后传给它的儿子。此时它的儿子不必处理,直到要处理到它的儿子为止。
下面是这强大的update代码:
void update(long k)
{
if (a[k].cnt==0) return;
a[k].sum+=(a[k].r-a[k].l+1)*a[k].cnt;
a[k*2].cnt+=a[k].cnt;a[k*2+1].cnt+=a[k].cnt;
a[k].cnt=0;
}
每次处理到k时,先做一遍update(k)再进行操作即可。
------------------------------------------------回到原题-------------------------------------------------------
这里可能相对简单一些,下面说一些与模板不太相同的细节。
(1)初始建树时,每个值都是0.
(2)在插入时,每次cnt累加1即可,这个1当然不是加上1,而是执行操作数。
(3)在update中,如果cnt是偶数,就可以直接清零(因为偶数次不是抵消了嘛!);如果是奇数,我们把它相反一下,并向下传1。
代码:
#include<stdio.h>
using namespace std;
const long maxn=100001;
struct tree
{
long l,r; //l和r就是a[i]所表示的左右区间范围。
long cnt,sum; //cnt是累加的操作次数,sum是a[i]表示的线段中开着的灯的数量。
}a[4*maxn];
long n,m,i,x,y,ok;
void build(long k,long l,long r) //基础建树
{
a[k].cnt=0;a[k].l=l;a[k].r=r;
if (l==r) return;
long mid=(l+r)/2;
build(k*2,l,mid);build(k*2+1,mid+1,r);
}
void update(long k) //update操作。
{
if (a[k].cnt==0) return;
if (a[k].cnt%2==1)
{
a[k].sum=a[k].r-a[k].l+1-a[k].sum; //a[k]的区间是a[k].l到a[k].r,那么共有a[k].r-a[k].l+1个,这里取反。
a[k*2].cnt+=1;a[k*2+1].cnt+=1;
a[k].cnt=0;
}
else a[k].cnt=0;
}
void ins(long k,long l,long r)
{
update(k);
if (a[k].l>=l&&a[k].r<=r) {a[k].cnt+=1;return;} //当前区域被覆盖
long mid=(a[k].l+a[k].r)/2; //二分找被覆盖的区域。
if (l<=mid) ins(k*2,l,r);
if (r>mid) ins(k*2+1,l,r);
update(k*2);update(k*2+1); //对儿子的更新操作(很重要),因为下面一步要重新更新当前的值。
a[k].sum=a[k*2].sum+a[k*2+1].sum;
}
long find(long k,long l,long r) //这与ins大同小异。
{
update(k);
if (a[k].l>=l&&a[k].r<=r) return a[k].sum;
long mid=(a[k].l+a[k].r)/2,o=0;
if (l<=mid) o+=find(k*2,l,r);
if (r>mid) o+=find(k*2+1,l,r);
update(k*2);update(k*2+1);
a[k].sum=a[k*2].sum+a[k*2+1].sum;
return o;
}
int main()
{
//freopen("lites.in","r",stdin);
//freopen("lites.out","w",stdout);
scanf("%ld%ld",&n,&m);
build(1,1,n);
for (i=1;i<=m;i++)
{
scanf("%ld%ld%ld",&ok,&x,&y);
if (ok==0) ins(1,x,y);
else {long ans=find(1,x,y);printf("%ld\n",ans);}
}
//scanf("%ld",&n,&m);
return 0;
}
usaco 2008 月赛 lites 开关灯 题解的更多相关文章
- usaco 2002 月赛 Fiber Communications 题解
Description Farmer John wants to connect his N (1 <= N <= 1,000) barns (numbered 1..N) with a ...
- bzoj usaco 金组水题题解(1)
UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT. ...
- 1230: [Usaco2008 Nov]lites 开关灯
1230: [Usaco2008 Nov]lites 开关灯 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1162 Solved: 589[Sub ...
- Code[VS]1690 开关灯 题解
Code[VS]1690 开关灯 题解 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description: YYX家门前 ...
- BZOJ 1230: [Usaco2008 Nov]lites 开关灯( 线段树 )
线段树.. --------------------------------------------------------------------------------- #include< ...
- usaco 2002 月赛 Chores 题解
Description Farmer John's family pitches in with the chores during milking, doing all the chores as ...
- USACO全部月赛及GateWay数据
月赛: 以07年open为例,网站如下 http://contest.usaco.org/OPEN07 其他的格式是http://contest.usaco.org/月份(月份的英文前三位,比如1月是 ...
- ZOJ Monthly, June 2014 月赛BCDEFGH题题解
比赛链接:点击打开链接 上来先搞了f.c,,然后发现状态不正确,一下午都是脑洞大开,, 无脑wa,无脑ce...一样的错犯2次.. 硬着头皮搞了几发,最后20分钟码了一下G,不知道为什么把1直接当成不 ...
- USACO section 1.1 C++题解
USACO section1.1:DONE 2017.03.03 TEXT Submitting Solutions DONE 2017.03.04 PROB Your Ride Is Here [A ...
随机推荐
- 【CSS Cookbook】笔记摘要(一)
概要 CSS的优点:将表现和内容相分离:更好地控制页面布局:大大减少了文件尺寸:缩短了改版时间:提高了易用性. CSS全称层叠式样表(Cascading Style Sheets). 1.问题:如何最 ...
- 机器学习:Python实现聚类算法(一)之K-Means
1.简介 K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一.K-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类.通过迭代的方法,逐次更新各 ...
- php微信支付问题之 cURL error 60: SSL certificate: unable to get local issuer certificate
cacert.pem(点击下载) 解决办法:比如我本地安装的是wamp,将cacert.pem文件放在这个文件夹下面D:\wamp\bin\php\php5.5.12\ext 如果安装的phpStud ...
- [原创]CentOS下Mysql双机互为备份
一.环境: 1.安装Centos-6.5-x64位系统的机器两台: host1:192.168.2.3 host2:192.168.2.4 (互相能ping通) 2.安装Mysql. 命令:Yum ...
- CentOS上安装NodeJs
(1)参照:http://www.cnblogs.com/zhangqingsh/archive/2013/04/15/3022583.html 安装Python2.7 (2)安装Nodejs yu ...
- mysql too many connections 问题
我的处理步骤: 第一步:首次确定你的服务可不可以重启,如果可以重启转第二步,如果不可以重启转第三步,这个主要考虑已经部署到客户现场或者正在使用中的数据库不能重启. 第二步:查找mysql的安装路径,这 ...
- mac Path had bad ownership/permissions
解决方案: http://stackoverflow.com/questions/28063598/error-while-executing-plist-file-path-had-bad-owne ...
- RMAN备份与恢复(二)--常用操作学习
(1)连接目标数据库 在RMAN中可以建立与目标数据库或恢复目录数据库的连接.与目标数据库连接时,用户须具有sysdba系统权限,以保证可以进行数据库的备份.修复与恢复工作. 可以在操作系统命令提示符 ...
- 常见浏览器User-Agent大全
http://blog.csdn.net/tianjinjianzhan/article/details/51702232
- Blockly编程:用Scratch制作游戏愤怒的小牛(小鸟)
愤怒的小鸟曾经很热门,网上还说他是程序员最喜欢玩的游戏.最先我是WIKIOI的评测页面看到他的,后来在2014年全国信息学奥林匹克联赛第一天第三题飞扬的小鸟也看到了它.因此,突然想做一个类似愤怒的小鸟 ...