题目: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. vue组件---动态组件之多标签页面

    首先看下效果图 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> & ...

  2. valgrind检查代码内存泄漏,5种内存泄漏情况

    摘要: valgrind是linux下用于调试程序和查找内存泄露的常用工具.valgrind会报告5种内存泄露,"definitely lost", "indirectl ...

  3. RabbitMq的简单使用

    本篇将介绍RabbitMq的一个简单使用例子,分别介绍生产者如何发送消息,消费者如何接收和处理消息 关于RabbitMQ的知识背景的文章非常多.我对它的总结是,解决高并发请求的瓶颈,将应用程序真正处理 ...

  4. 【Codeforces 1073D】Berland Fair

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 我们可以从左到右枚举一轮. 定义一个cost表示这一轮花费的钱数 如果cost+a[i]<=T那么就可以买它,并且买下它(模拟题目要求) ...

  5. [BZOJ2843] 极地旅行社(LCT)

    传送门 模板. ——代码 #include <cstdio> #include <iostream> #define N 300001 #define get(x) (son[ ...

  6. MySQL大小写问题的简单说明(关键字/函数/表名)(转)

    MySQL语句中字母大小写规则随着语句元素的不同而变化,同时还要取决于MySQL服务器主机上的操作系统. SQL关键字与函数名 关键字和函数名不区分字母的大小写.如.abs.bin.now.versi ...

  7. Pivotal-tc-Server与Tomcat区别

    Pivotal-tc-Server之前叫做SpringSource tc Server,包含三个版本分别是:Spring版.标准版和开发版,但其中只有开发版是免费的.比如在STS中包含的版本就是开发板 ...

  8. jquery simple modal

    窗体API定义丰富,而且使用也很容易上手.官方地址:http://www.ericmmartin.com/projects/simplemodal/从官方下载插件,在文件中引用<script t ...

  9. C语言的数组初始化

    http://blog.csdn.net/sibylle/article/details/2026915 一直以为 int a[256]={0};是把a的所有元素初始化为0,int a[256]={1 ...

  10. tar 查看压缩包内容