「Code+#2」火锅盛宴
作者:互联网
博主的 BiBi 时间
话说因为这道题当天下午去吃了火锅,结果一身味。。。
明明只打了 \(8pts\) 却意外收获 \(15pts\)!
竟然会用 \(set\) 了 \(QwQ\)。
Code
#include <set>
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1e5 + 5, Q = 5e5 + 5;
int n, q, a[N], tot[N], sum[N << 2];
set <int> s;
set <int> :: iterator it;
int read() {
int x = 0, f = 1; char s;
while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
return x * f;
}
int query(const int o, const int l, const int r, const int L, const int R) {
if(l > R || r < L) return 0;
if(l >= L && r <= R) return sum[o];
int mid = l + r >> 1;
return query(o << 1, l, mid, L, R) + query(o << 1 | 1, mid + 1, r, L, R);
}
void pushUp(const int o) {
if(! o) return;
sum[o] = sum[o << 1] + sum[o << 1 | 1];
return;
}
void update(const int o, const int l, const int r, const int p, const int k) {
if(l > p || r < p) return;
if(l == r) {
sum[o] += k;
return;
}
int mid = l + r >> 1;
update(o << 1, l, mid, p, k); update(o << 1 | 1, mid + 1, r, p, k);
pushUp(o);
}
int main() {
int op, x, y;
for(int T = read(); T; -- T) {
n = read(); s.clear();
for(int i = 1; i <= n; ++ i) a[i] = read(), tot[i] = 0;
for(int i = 1; i <= (n << 2); ++ i) sum[i] = 0;
q = read();
while(q --) {
x = read(); op = read();
if(op == 0) {
x = read();
if(! tot[x]) s.insert(x);
update(1, 1, n, x, 1); ++ tot[x];
}
else if(op == 1) {
if(s.empty()) puts("Yazid is angry.");
else {
it = s.begin();
printf("%d\n", *it);
-- tot[*it];
update(1, 1, n, *it, -1);
if(tot[*it] == 0) s.erase(*it);
}
}
else if(op == 2) {
x = read();
if(tot[x]) {
puts("Succeeded!");
update(1, 1, n, x, -1);
-- tot[x];
if(tot[x] == 0) s.erase(x);
}
else puts("YJQQQAQ is angry.");
}
else {
x = read(), y = read();
printf("%d\n", query(1, 1, n, x, y));
}
}
}
return 0;
}
Solution
其实这道题的方法有很多,比如我旁边的那位用了线段树+优先队列,某谷上只有 \(30pts\),不过在 \(usOJ\) 上能过就行了。
我是用的 树状数组+模拟链表。(太棒了学到许多)
用链表来维护每种食物下锅情况。定义 \(head[i]\) 为第 \(i\) 种食物的表头,\(tail[i]\) 为表尾。\(nxt\) 数组用来表示连接关系。
用树状数组来维护每种食物可以出锅的个数。
另外这里的 \(upper\) 是树状数组中第一个大于某个值的的下标。(另外这里不会证明,有什么大佬可以证一下吗)
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5, Q = 5e5 + 5;
int n, q, s[N], t[Q], op[Q], a[Q], b[Q], id[Q], cnt, head[N], nxt[Q], tail[N], data[Q], tot;
struct BIT {
int sum[N];
void clear() {memset(sum, 0, sizeof sum);}
int lowbit(const int x) {return x & -x;}
void update(int x, const int k) {
while(x <= n) sum[x] += k, x += lowbit(x);
}
int query(int x) {
int r = 0;
while(x) r += sum[x], x -= lowbit(x);
return r;
}
int upper(const int lim) {
int x = 0, r = 0;
for(int i = (1 << 16); i; i >>= 1)
if(x + i <= n && r + sum[x + i] <= lim) r += sum[x += i];
return x + 1;
}
} bit;
int read() {
int x = 0, f = 1; char s;
while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
return x * f;
}
bool cmp(const int x, const int y) {return t[x] + s[a[x]] < t[y] + s[a[y]];}
void add(const int x, const int k) {
if(! head[x]) head[x] = tail[x] = ++ tot;
else nxt[tail[x]] = ++ tot, tail[x] = tot;
data[tot] = k;
}
void Insert(const int x) {
bit.update(x, 1);
head[x] = nxt[head[x]];
if(! head[x]) tail[x] = 0;
}
int main() {
for(int T = read(); T; -- T) {
cnt = tot = 0;
memset(head, 0, sizeof head);
memset(tail, 0, sizeof tail);
memset(nxt, 0, sizeof nxt);
n = read(); bit.clear();
for(int i = 1; i <= n; ++ i) s[i] = read();
q = read();
for(int i = 1; i <= q; ++ i) {
t[i] = read(), op[i] = read();
if(op[i] == 0) a[i] = read(), id[++ cnt] = i;
else if(op[i] == 2) a[i] = read();
else if(op[i] == 3) a[i] = read(), b[i] = read();
}
sort(id + 1, id + cnt + 1, cmp);
int p = 1;
for(int i = 1; i <= q; ++ i) {
while(p <= cnt && t[id[p]] + s[a[id[p]]] <= t[i]) Insert(a[id[p]]), ++ p;
if(op[i] == 0) add(a[i], t[i] + s[a[i]]);
else if(op[i] == 1) {
int tmp = bit.upper(0);
if(tmp == n + 1) puts("Yazid is angry.");
else printf("%d\n", tmp), bit.update(tmp, -1);
}
else if(op[i] == 2) {
if(bit.query(a[i]) - bit.query(a[i] - 1)) puts("Succeeded!"), bit.update(a[i], -1);
else if(head[a[i]]) printf("%d\n", data[head[a[i]]] - t[i]);
else puts("YJQQQAQ is angry.");
}
else printf("%d\n", bit.query(b[i]) - bit.query(a[i] - 1));
}
}
return 0;
}
标签:+#,Code,return,火锅,int,sum,while,const,include 来源: https://www.cnblogs.com/AWhiteWall/p/13025603.html