题目: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. Oracle RAC 后台进程

    LMS  - Gobal         全局缓存服务进程 LMD  - Global Enqueue Service Daemon 全局查询服务守护进程 LMON -  全局服务器监控进程 LCK0 ...

  2. jquery 五星评价(图片实现)

    1111 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...

  3. 3D NAND闪存是个啥?让国内如此疯狂

    Repost: https://news.mydrivers.com/1/477/477251.htm 上个月底武汉新芯科技主导的国家级存储器产业基地正式动工,在大基金的支持下该项目将投资240亿美元 ...

  4. Stuts2学习——HelloWorld

    这两天从对Struts一窍不通到成功运行HelloWorld,在SSH这条路上迈出了第一步. 下面我把我的第一个Struts程序放上来: 一.新建web project,配置文件等准备工作 1. 新建 ...

  5. P1616 疯狂的采药(洛谷,动态规划递推,完全背包)

    先上题目链接:P1616 疯狂的采药 然后放AC代码: #include<bits/stdc++.h> #define ll long long using namespace std; ...

  6. 每日命令:(3)pwd

    Linux中用 pwd 命令来查看”当前工作目录“的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置. ...

  7. Nginx+Tomcat简单负载均衡

    Nginx,Apache安装完成 复制Tomcat:    tomcat-8080    tomcat-8081 启动Tomcat8080: cd /usr/local/tomcat-8080/bin ...

  8. 来说一说chrome扩展和chrome插件到底有什么区别?

    想讨论chrome扩展和chrome插件区别这个话题很久了!但是迟迟没有写.因为我自己也没有搞清楚这两者之间的区别!回想当初是因为需要寻找番羽墙插件才想到去搜索到chrome插件. 想讨论chrome ...

  9. OS X中crt中文乱码

    SecureCRT中显示乱码的话,可以去设置为UTF-8编码: Session Options->Terminal->Appearance->Character Encoding,设 ...

  10. Spring 4 整合RMI技术及发布多个服务(xjl456852原创)

    rmi需要建立两个项目,一个是服务端的项目,一个是客户端的项目.服务端项目启动后,再启动客户端项目去调用服务端的方法. 我们建立两个maven项目: pom.xml配置: <?xml versi ...