火车经过X站,火车最大载客人数为m,有n个订票请求,请求订购从a站到b站的k张票,若能满足订购要求则输出1,否则输出0。
半个月终于刷完了NK的200多道题,没想到在最后这里会遇到线段苏,首先,暴力很好写,维护一个区间,区间值初始为m,每次一个查询就把相应区间的载客人数减去相应人数,如果不够减就是0,否则为1,但是这道题很骚,不给数据范围,试了之后发现不行,数据太大
链接:https://www.nowcoder.com/questionTerminal/e65887ca7bf14b1b947073f544a6f4f4?f=discussion
来源:牛客网
不通过
您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为14.74%
用例:
463426784 999969204 415
对应输出应该为:
1
你的输出为:
空.请检查一下你的代码,有没有循环输入处理多个case.
对这种情况,显然需要一手离散化,离散之后再进行操作,however,离散化后的效率依然跟不上
struct E {
ll from, to, num;
E(ll a = 0, ll b = 0, ll c = 0) { from = a, to = b, num = c; }
};
int main() {
ll n, m;
while (cin >> n >> m) {
//v1存储所有的请求 v2存储离散化后的站点
vector<E> v1; set<ll> s; vec v2, v3;
ll a, b, c;
for (int i = 0; i < n; i++) {
cin >> a >> b >> c; v1.push_back(E(a, b, c));
s.insert(a); s.insert(b); //离散化
}
for (set<ll>::iterator i = s.begin(); i != s.end(); i++)
v2.push_back((*i)),v3.push_back(m); //将离散化后的所有站点存储到vector中
sort(v2.begin(), v2.end());//从小到大排序
for (unsigned i = 0; i < v1.size(); i++) {
E t = v1[i];
ll id1 = lower_bound(v2.begin(), v2.end(), t.from) - v2.begin();
ll id2 = lower_bound(v2.begin(), v2.end(), t.to) - v2.begin();
ll maxN = 0, num = t.num, sign = 1;
if (num > m) { cout << 0 << endl; continue; }
for (int j = id1; j <= id2 && sign; j++) {
if (v3[j] < num) { sign = 0; break; }//该位置没有这么多名额了
}
if (sign) {
cout << 1 << endl;
for (int j = id1; j <= id2 && sign; j++)
v3[j] -= num;
}
else cout << 0 << endl;
}
}
}
此时我们注意到,这个问题完全是一个区间修改,区间查询的问题,我们不断的修改某个区间的值(买票上车),判断能否满足订购要求时需要查询这一段区间内的最小值,经典的RMQ问题,直接线段树即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 100000
using namespace std;
int tree[MAX << 3], lazy[MAX << 3];
int a[MAX], b[MAX], k[MAX];
int discrete(int* a, int* b, int n) {
int temp[MAX << 1], len = 0;
for(int i = 0; i < n; i++) {
temp[len++] = a[i];
temp[len++] = b[i];
}
sort(temp, temp + len);
len = unique(temp, temp + len) - temp;
for(int i = 0; i < n; i++) {
a[i] = lower_bound(temp, temp + len, a[i]) - temp;
b[i] = lower_bound(temp, temp + len, b[i]) - temp;
}
return len;
}
int getmax(int a, int b) {
return a >= b ? a : b;
}
void build() {
memset(tree, 0, sizeof(tree));
memset(lazy, 0, sizeof(lazy));
return;
}
void pushup(int root) {
tree[root] = getmax(tree[root << 1], tree[root << 1 | 1]);
return;
}
void pushdown(int root) {
if(lazy[root] == 0) return;
tree[root << 1] += lazy[root];
tree[root << 1 | 1] += lazy[root];
lazy[root << 1] += lazy[root];
lazy[root << 1 | 1] += lazy[root];
lazy[root] = 0;
return;
}
void update(int a, int b, int k, int l, int r, int root) {
if(a <= l && r <= b) {
tree[root] += k;
lazy[root] += k;
return;
}
pushdown(root);
int mid = (l + r) >> 1;
if(a <= mid) update(a, b, k, l, mid, root << 1);
if(mid + 1 <= b) update(a, b, k, mid + 1, r, root << 1 | 1);
pushup(root);
}
int query(int a, int b, int l, int r, int root) {
int ans = 0;
if(a <= l && r <= b) return tree[root];
pushdown(root);
int mid = (l + r) >> 1;
if(a <= mid) ans = getmax(ans, query(a, b, l, mid, root << 1));
if(mid + 1 <= b) ans = getmax(ans, query(a, b, mid + 1, r, root << 1 | 1));
return ans;
}
int main() {
int n = 0, m = 0, len = 0;
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 0; i < n; i++)
scanf("%d%d%d", &a[i], &b[i], &k[i]);
//建树
build();
//对所有车站做离散化并拿到真实的车站数
len = discrete(a, b, n);
for(int i = 0; i < n; i++) {
//区间查询+区间修改
if(query(a[i], b[i], 0, len - 1, 1) + k[i] <= m) {
update(a[i], b[i], k[i], 0, len - 1, 1);
printf("1\n");
}
else printf("0\n");
}
}
return 0;
}