题目: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 ] 借教室 —— 线段树 / 二分差分数组的更多相关文章

  1. 洛谷P4243/bzoj1558 [JSOI2009]等差数列(线段树维护差分+爆炸恶心的合并)

    题面 首先感谢这篇题解,是思路来源 看到等差数列,就会想到差分,又有区间加,很容易想到线段树维护差分.再注意点细节,\(A\)操作完美解决 然后就是爆炸恶心的\(B\)操作,之前看一堆题解的解释都不怎 ...

  2. 【洛谷P1083】[NOIP2012]借教室

    借教室 [题目描述] 在n天中每天有一个可以借出的教室数,有m个订单,每个订单从第l天到第r天要借用x个教室.问能否满足所有的订单,若不能,输出第一个不能满足的订单编号. 思路: 1.1 ≤ n,m ...

  3. 题解【洛谷P1083】[NOIP2012]借教室

    题面 二分到哪一个申请人要修改订单,可以差分\(+\)前缀和达到\(\Theta(n)\)的\(\text{check}\). 具体细节见代码. #include <bits/stdc++.h& ...

  4. 洛谷P1438 无聊的数列 (线段树+差分)

    变了个花样,在l~r区间加上一个等差数列,等差数列的显著特点就是公差d,我们容易想到用线段树维护差分数组,在l位置加上k,在l+1~r位置加上d,最后在r+1位置减去k+(l-r)*d,这样就是在差分 ...

  5. NOIP 2012 借教室

    洛谷 P1083 借教室 https://www.luogu.org/problem/P1083 JDOJ 1783: [NOIP2012]借教室 D2 T2 https://neooj.com/ol ...

  6. noip 2012 借教室 (线段树 二分)

    /* 维护区间最小值 数据不超int 相反如果long long的话会有一组数据超时 无视掉 ll int */ #include<iostream> #include<cstdio ...

  7. noip 借教室 线段树95分做法

    大致的思路是用线段树维护每个区间内部的最小值 段更新最小值 每次查某个区间的最小值是否满足租借要求 满足就借出去 update最小值 注意pushdown操作  还有一个从子区间提取答案的操作 提交地 ...

  8. NOIP2012借教室[线段树|离线 差分 二分答案]

    题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自 ...

  9. 洛谷P3434 [POI2006]KRA-The Disks(线段树)

    洛谷题目传送门 \(O(n)\)的正解算法对我这个小蒟蒻真的还有点思维难度.洛谷题解里都讲得很好. 考试的时候一看到300000就直接去想各种带log的做法了,反正不怕T...... 我永远只会有最直 ...

随机推荐

  1. java虚拟机(三)--HotSpot 对象

    普通对象的创建(不包括数组和class对象): 当虚拟机遇到new指令时,会在常量池中检查是否包含这个类的符号引用(全限定名),通过这个确定是否经过类加载的过程,如果true,为该 对象分配内存,对象 ...

  2. linux 挂载数据盘

    完整的阿里云挂载数据盘方法如下: 1.入手阿里云后查看有几块硬盘:(只显示概况,不显示分区情况) fdisk -l|grep Disk 2.查看硬盘分区 fdisk -l 如果有提示:disk /de ...

  3. wpf 自定义单选按钮 RadioButton

    新建RadioButtonEx.cs public class RadioButtonEx : RadioButton { public Geometry SelectIcon { get { ret ...

  4. CentOS 7中firewall防火墙详解和配置以及切换为iptables防火墙--转载

    最近在linux(这里用到的是Centos7的64位版本)安装nginx时,在开放80端口时用iptables设置端口 和重启服务发现提示未找到文件,在网络上收集查找后发现在Centos7中iptab ...

  5. Python常用的内建模块

    PS:Python之所以自称“batteries included”,就是因为内置了许多非常有用的模块,无需额外安装和配置,即可直接使用.下面就来看看一些常用的内建模块. 参考原文 廖雪峰常用的内建模 ...

  6. JPA @MappedSuperclass注解

    该注解只能引用于类上,使用该注解的类将不是一个完整的类,不会映射到数据库的表中,但是该类的属性会映射到其子类的数据库字段中 @MappedSuperclass注解使用在父类上面,是用来标识父类的作用 ...

  7. 部署web服务器的配置——补充mysql和tomcat

    今天想到了关于mysql的一些配置,以后关于配置mysql和tomcat相关的内容也会补充在这里. tomcat: 1. 更改内存(要设置tomcat内存,解决内存溢出的问题):安装版tomcat,打 ...

  8. 2018NOIP普及T4---对称二叉树

    题目 对称二叉树   题目描述 思路 检查是否符合对称条件 条件很简单——结构对称&&点权对称 要做到点权对称其实也就顺便结构对称了 于是条件可以简化为点权对称 可以考虑并行搜索 bo ...

  9. static private 与 final 的用法总结

    1.static表示静态.他是属于类的.可以在本身类里直接调用,或在其它类里用类名.方法名调用.不加static表示是实例的方法,必须用实例来调用.在本类里也一样,必须用实例调用 2.private是 ...

  10. Linux mpstat-显示各个可用CPU的状态

    更多linux 性能监测与优化 关注:linux命令大全 mpstat命令指令主要用于多CPU环境下,它显示各个可用CPU的状态系你想.这些信息存放在/proc/stat文件中.在多CPUs系统里,其 ...