洛谷 P1083 [ NOIP 2012 ] 借教室 —— 线段树 / 二分差分数组
题目:https://www.luogu.org/problemnew/show/P1083
当初不会线段树的时候做这道题...对差分什么不太熟练,一直没A,放在那儿不管...
现在去看,线段树就直接秒了;
不过要注意一下基本的细节囧...
但本题 n 的范围比较微妙,正常线段树会 T 一个点(不过运气好也能过);
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e6+,maxm=2e7+;
int n,m,a[maxn],mn[maxm],ls[maxm],rs[maxm],cnt=,lzy[maxm];//cnt=1!!
bool fl=;
void pushup(int x){mn[x]=min(mn[ls[x]],mn[rs[x]]);}
void pushdown(int x)
{
if(!lzy[x])return;
lzy[ls[x]]+=lzy[x]; lzy[rs[x]]+=lzy[x];
mn[ls[x]]+=lzy[x]; mn[rs[x]]+=lzy[x];
lzy[x]=;
}
void build(int x,int l,int r)
{
if(l==r){mn[x]=a[l]; return;}
int mid=((l+r)>>);
ls[x]=++cnt; build(ls[x],l,mid);
rs[x]=++cnt,build(rs[x],mid+,r);
pushup(x);
}
void update(int x,int l,int r,int L,int R,int val)
{
if(l>=L&&r<=R){mn[x]+=val; lzy[x]+=val; return;}
pushdown(x); int mid=((l+r)>>);
if(mid>=L)update(ls[x],l,mid,L,R,val);
if(mid<R)update(rs[x],mid+,r,L,R,val);
pushup(x);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
build(,,n);
for(int i=,s,t,r;i<=m;i++)
{
scanf("%d%d%d",&r,&s,&t);
if(fl)continue;
update(,,n,s,t,-r);
if(mn[]<){printf("-1\n%d\n",i); fl=;}
}
if(!fl)printf("0\n");
return ;
}
T #13
所以要加个标记永久化。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e6+,maxm=2e7+;
int n,m,a[maxn],mn[maxm],ls[maxm],rs[maxm],cnt=,lzy[maxm];//cnt=1!!
bool fl=;
void pushup(int x){mn[x]=min(mn[ls[x]]+lzy[ls[x]],mn[rs[x]]+lzy[rs[x]]);}//+!
void build(int x,int l,int r)
{
if(l==r){mn[x]=a[l]; return;}
int mid=((l+r)>>);
ls[x]=++cnt; build(ls[x],l,mid);
rs[x]=++cnt,build(rs[x],mid+,r);
// pushup(x);
mn[x]=min(mn[ls[x]],mn[rs[x]]);//
}
void update(int x,int l,int r,int L,int R,int val)
{
if(l==L&&r==R){lzy[x]+=val; return;}
int mid=((l+r)>>);
if(mid<L)update(rs[x],mid+,r,L,R,val);
else if(mid>=R)update(ls[x],l,mid,L,R,val);
else update(ls[x],l,mid,L,mid,val),update(rs[x],mid+,r,mid+,R,val);
pushup(x);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
build(,,n);
for(int i=,s,t,r;i<=m;i++)
{
scanf("%d%d%d",&r,&s,&t);
if(fl)continue;
update(,,n,s,t,-r);
if(mn[]-lzy[]<){printf("-1\n%d\n",i); fl=;}
}
if(!fl)printf("0\n");
return ;
}
还有一种二分差分数组的做法,其实很暴力;
不是开两个差分数组每次 memcpy ,而是只开一个记录减少量和原数组比较,会快一点。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e6+;
int n,m,s[maxn],t[maxn],c[maxn],r[maxn],d[maxn];
bool ck(int mid)
{
memset(c,,sizeof c);
for(int i=;i<=mid;i++)c[s[i]]+=r[i],c[t[i]+]-=r[i];
bool fl=; int tmp=;
for(int i=;i<=n;i++)
{
tmp+=c[i];
if(d[i]-tmp<){fl=; break;}
}
return fl;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,pre=;i<=n;i++)scanf("%d",&d[i]);
for(int i=;i<=m;i++)scanf("%d%d%d",&r[i],&s[i],&t[i]);
int l=,r=m,ans=-;
while(l<=r)
{
int mid=((l+r)>>);
if(ck(mid))ans=mid,r=mid-;
else l=mid+;
}
if(ans==-)printf("0\n");
else printf("-1\n%d\n",ans);
return ;
}
洛谷 P1083 [ NOIP 2012 ] 借教室 —— 线段树 / 二分差分数组的更多相关文章
- 洛谷P4243/bzoj1558 [JSOI2009]等差数列(线段树维护差分+爆炸恶心的合并)
题面 首先感谢这篇题解,是思路来源 看到等差数列,就会想到差分,又有区间加,很容易想到线段树维护差分.再注意点细节,\(A\)操作完美解决 然后就是爆炸恶心的\(B\)操作,之前看一堆题解的解释都不怎 ...
- 【洛谷P1083】[NOIP2012]借教室
借教室 [题目描述] 在n天中每天有一个可以借出的教室数,有m个订单,每个订单从第l天到第r天要借用x个教室.问能否满足所有的订单,若不能,输出第一个不能满足的订单编号. 思路: 1.1 ≤ n,m ...
- 题解【洛谷P1083】[NOIP2012]借教室
题面 二分到哪一个申请人要修改订单,可以差分\(+\)前缀和达到\(\Theta(n)\)的\(\text{check}\). 具体细节见代码. #include <bits/stdc++.h& ...
- 洛谷P1438 无聊的数列 (线段树+差分)
变了个花样,在l~r区间加上一个等差数列,等差数列的显著特点就是公差d,我们容易想到用线段树维护差分数组,在l位置加上k,在l+1~r位置加上d,最后在r+1位置减去k+(l-r)*d,这样就是在差分 ...
- NOIP 2012 借教室
洛谷 P1083 借教室 https://www.luogu.org/problem/P1083 JDOJ 1783: [NOIP2012]借教室 D2 T2 https://neooj.com/ol ...
- noip 2012 借教室 (线段树 二分)
/* 维护区间最小值 数据不超int 相反如果long long的话会有一组数据超时 无视掉 ll int */ #include<iostream> #include<cstdio ...
- noip 借教室 线段树95分做法
大致的思路是用线段树维护每个区间内部的最小值 段更新最小值 每次查某个区间的最小值是否满足租借要求 满足就借出去 update最小值 注意pushdown操作 还有一个从子区间提取答案的操作 提交地 ...
- NOIP2012借教室[线段树|离线 差分 二分答案]
题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自 ...
- 洛谷P3434 [POI2006]KRA-The Disks(线段树)
洛谷题目传送门 \(O(n)\)的正解算法对我这个小蒟蒻真的还有点思维难度.洛谷题解里都讲得很好. 考试的时候一看到300000就直接去想各种带log的做法了,反正不怕T...... 我永远只会有最直 ...
随机推荐
- pringboot开启找回Run Dashboard
代码中加入 <option name="configurationTypes"> <set> <option value="SpringBo ...
- 用Docker实现nginx多端口
一.安装docker 需要阿里的epel源,需要联网 [root@bogon ~]#yum -y install docker [root@bogon ~]#systemctl start docke ...
- FileOutputStream将从一个文件中读取的内容写到另一个文件中
package com.janson.day2018082 import java.io.FileInputStream; import java.io.FileNotFoundException; ...
- 10 Minutes to pandas中文版
本文是对pandas官方网站上<10 Minutes to pandas>的一个简单的翻译,原文在这里.这篇文章是对pandas的一个简单的介绍,详细的介绍请参考:Cookbook .习惯 ...
- JDBC在Java Web中的应用
JDBC在Java Web中的应用 制作人:全心全意 在Java Web开发中,JDBC的应用十分广泛.通常情况下,Web程序操作数据库都是通过JDBC实现,即使目前数据库方面的开源框架层出不穷,但其 ...
- circumferential averaged streamwise velocity in ParaView
Goal: get a averaged axial velocity in a circular loop (dashed line in the following figure) Steps: ...
- 多校1010 Taotao Picks Apples
>>点击进入原题<< 思路:题解很有意思,适合线段树进阶 #include<cstdio> #include<cmath> #include<cs ...
- Arduino 测试空气质量等级模块 ZP07-MP503 测试
最近入手空气质量模块 ZP07-MP503,用Arduino采样数据进行测试 先上图看看 ZP07-MP503 产品 ZP07-MP503 一共4个管脚,功能如下 5V 电源输入5V GND 电源输 ...
- node-sass 安装失败
安装 npm install 时偶尔遇到报错:没有安装python或node-sass 安装失败的问题,百度之后发现是被墙了,但根据百度的方法换了淘宝镜像和用了vpn都安装失败, 原因可能是没有卸载之 ...
- SHA256兼容性
SHA-2是一个加密哈希(Cryptographic Hash)函数的一个集合,包括SHA-224,SHA256和SHA-512.在SHA-256中的256代表哈希(Hash)输出或者摘要的位尺寸(即 ...