题目描述
在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。
面对海量租借教室的信息,我们自然希望编程解决这个问题。
我们需要处理接下来$n$天的借教室信息,其中第ii天学校有$r_i$
个教室可供租借。共有$m$份订单,每份订单用三个正整数描述,分别为$d_j,s_j,t_j$ ,表示某租借者需要从第$s_j$天到第$t_j$天租借教室(包括第$s_j$天和第$t_j$天),每天需要租借$d_j$个教室。
我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供$d_j$个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。
借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第$s_j$天到第$t_j$天中有至少一天剩余的教室数量不足$d_j$个。
现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。
输入格式
第一行包含两个正整数$n,m$,表示天数和订单的数量。
第二行包含$n$个正整数,其中第$i$个数为$r_i$
,表示第$i$天可用于租借的教室数量。
接下来有$m$行,每行包含三个正整数$d_j,s_j,t_j$,表示租借的数量,租借开始、结束分别在第几天。
每行相邻的两个数之间均用一个空格隔开。天数与订单均用从$1$开始的整数编号。
输出格式
如果所有订单均可满足,则输出只有一行,包含一个整数$0$。否则(订单无法完全满足)
输出两行,第一行输出一个负整数$-1$,第二行输出需要修改订单的申请人编号。
题解
题目看了一半的时候以为是二分答案,后来。。。。
这不就是个线段树么
题意很明确,让你维护一个区间,每次给这段区间加上1,之后判断它的值是否超出了给定的界限。
这样维护很麻烦,我们可以逆向操作。
先给线段树赋上最大租借的教室数,之后区间减一,一旦有一个数小于零的话,说明教室不够了,输出便可。
代码(这次线段树写的比较毒瘤)
#include <iostream>
using namespace std;
namespace my
{
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define maxn 2000006
class segmentTree
{
public:
void build(int l, int r, int rt);
void modify(int l, int r, int rt, int fl, int fr, int x);
inline int find();
private:
inline int min(int x, int y);
inline void update(int rt);
inline void add(int l, int r, int rt, int x);
inline void push(int l, int r, int rt);
int z[maxn], tag[maxn];
};
inline int segmentTree::min(int x, int y)
{
return x > y ? y : x;
}
void segmentTree::build(int l, int r, int rt)
{
if(l == r)
{
cin >> z[rt];
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
update(rt);
}
inline void segmentTree::update(int rt)
{
z[rt] = min(z[rt << 1], z[rt << 1 | 1]);
}
void segmentTree::modify(int l, int r, int rt, int fl, int fr, int x)
{
if(l == fl and fr == r)
{
add(l, r, rt, x);
return;
}
push(l, r, rt);
int mid = (l + r) >> 1;
if(fl <= mid)
{
if(fr > mid) modify(lson, fl, mid, x), modify(rson, mid + 1, fr, x);
else modify(lson, fl, fr, x);
}
else
modify(rson, fl, fr, x);
update(rt);
}
inline int segmentTree::find()
{
return z[1];
}
inline void segmentTree::add(int l, int r, int rt, int x)
{
z[rt] -= x;
tag[rt] += x;
}
inline void segmentTree::push(int l, int r, int rt)
{
if(tag[rt])
{
int mid = (l + r) >> 1;
add(lson, tag[rt]);
add(rson, tag[rt]);
tag[rt] = 0;
}
}
#undef lson
#undef rson
#undef maxn
}
my::segmentTree t;
int n, m, d, l, r;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
t.build(1, n, 1);
for(register int i = 1; i <= m ;i++)
{
cin >> d >> l >> r;
t.modify(1, n, 1, l, r, d);
if(t.find() < 0)
{
cout << "-1\n" << i << endl;
return 0;
}
}
cout << "0";
return 0;
}
Comments NOTHING