借教室

来源:互联网 发布:微信一键群发软件免费 编辑:程序博客网 时间:2024/04/29 02:34

线段树+lazy

题目介绍:

在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。
教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。面对海量租借教室的信息,我们自然希望编程解决这个问题。
我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。
如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。
———————————分割—————————————-

输入:

输入文件为 classroom.in。第一行包含两个正整数n, m,表示天数和订单的数量。
第二行包含n个正整数,其中第i个数为ri,表示第i天可用于租借的教室数量。
接下来有m行,每行包含三个正整数dj, sj, tj ,表示租借的数量,租借开始、结束分别在第几天。每行相邻的两个数之间均用一个空格隔开。
天数与订单均用从1开始的整数编号。

输出:

输出文件为 classroom.out。
如果所有订单均可满足,则输出只有一行,包含一个整数 0。
否则(订单无法完全满足)输出两行,第一行输出一个负整数-1,第二行输出需要修改订单的申请人编号。

样例输入:

4 3 2 5 4 3 2 1 3 3 2 4 4 2 4

样例输出:

-1 2

数据范围:

对于 10%的数据,有1 ≤ n, m ≤ 10;
对于 30%的数据,有1 ≤ n, m ≤ 1000;
对于 70%的数据,有1 ≤ n, m ≤ 10^5;
对于 100%的数据,有1 ≤ n, m ≤ 10^6, 0 ≤ ri, dj≤ 10^9, 1 ≤ sj≤ tj≤ n。

—往下看

把题目抽空后:

给你一组数字,动态的对一段区间内的数减去一个值,只要这组数里出现了一个负数,就可以输出答案。

——-思路——-

动态的去除一段数,明显就是可以考虑线段树,树状数组一类的区间维护。

——-告诉你解法——-

解法一:二分+前缀和,可以稳过。(此方法我可没想,可以参考其他大牛。)
解法二:线段树+lazy,对于此题几乎可以过,但常数有些大,就有风险了。

——-解法二——-
用线段树维护这个区间,每次对一段区间进行操作时,打下lazy标记,对于每个询问只需要查询tree[1].min值就可以了。

以下为free pascal代码。

type        cy=record                value,labe:int64;        end;const maxn=1000005;var        a:array[0..maxn]of longint;        tree:array[0..4*maxn]of cy;        i,x,y,z,ans,n,m:longint;function        min(x,y:longint):longint;begin        if x<y then exit(x) else exit(y);end;procedure        maketree(p,l,r:longint);var        mid:longint;begin        if l=r then        begin                tree[p].value:=a[l];                tree[p].labe:=0;                exit;        end;        tree[p].labe:=0;        mid:=(l+r)>>1;        maketree(p*2,l,mid);        maketree(p*2+1,mid+1,r);        tree[p].value:=min(tree[p<<1].value,tree[p<<1+1].value);        tree[p].labe:=0;end;procedure        push(p:longint;x:int64);begin        inc(tree[p<<1].labe,x);        inc(tree[p<<1+1].labe,x);        dec(tree[p<<1].value,x);        dec(tree[p<<1+1].value,x);end;procedure        change(p,l,r,a,b,take:longint);var        mid:longint;begin        if (l=a)and(r=b) then        begin                tree[p].value:=tree[p].value-take;                tree[p].labe:=tree[p].labe+take;                exit;        end;        push(p,tree[p].labe);        tree[p].labe:=0;        mid:=(l+r)>>1;        if b<=mid then change(p*2,l,mid,a,b,take)        else if a>mid then change(p*2+1,mid+1,r,a,b,take)        else        begin                change(p*2,l,mid,a,mid,take);                change(p*2+1,mid+1,r,mid+1,b,take);        end;        tree[p].value:=min(tree[p<<1].value,tree[p<<1+1].value);end;begin        assign(input,'class.in'); reset(input);        assign(output,'class.out'); rewrite(output);        readln(n,m);        for i:=1 to n do read(a[i]);        maketree(1,1,n);        for i:=1 to m do        begin                readln(z,x,y);                change(1,1,n,x,y,z);                ans:=tree[1].value;                if ans<0 then                begin                        writeln(-1);                        writeln(i);                        halt;                end;        end;        writeln(0);        close(input); close(output);end.

今天就这样了。

这里写图片描述

0 2
原创粉丝点击