P5482 [JLOI2011]不等式组
维护多个形如 \(ax + b> c\) 的不等式,支持下面操作,操作 \(n\) 次
Add a b c
:表明要往不等式组添加一条不等式 \(ax+b>c\)Del i
:代表删除第 i 条添加的不等式(最先添加的是第 1 条)。Query k
:代表一个询问,即当 \(x=k\) 时,在当前不等式组内成立的不等式的数量。\(1 \leq n \leq 10^5, a,b,c\in[-10^8 , 10^8], k \in [-10^6, 10^6]\)
solution
将不等式变一下形,对 \(a\) 进行分类讨论
- 若 \(a = 0\)
不等式变为 \(b > c\),此时不等式与 \(x\) 无关,如果此时的 \(b > c\) 则不等式恒成立,sp++,否则不等式永远都不成立
- 若 \(a > 0\)
不等式变为 \(x > \frac{c- b}{a}\) ,因为 \(k \in [-10^6, 10^6]\), 如果此时 \(\frac{c- b}{a} > 10^6\) 不等式恒不成立,如果 \(\frac{c- b}{a} < -10^6\) 不等式恒成立,sp++,如果 \(-10^6<\frac{c- b}{a} < 10^6\) ,把 \(\frac{c- b}{a}\) 加到一个树状数组中
- 若 \(a < 0\)
和上面一个样,就是不等式变一下号就好了,如果在范围之内,就把 \(\frac{c- b}{a}\) 加到另一个树状数组中
最后答案就是 \(sp + sum1[1 - k] + sum2[k, 1e6]\)
后面那两项树状数组前缀和就能搞定了
/*
work by:Ariel
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define ll long long
using namespace std;
const int N = 1e6 + 1;;
int read() {
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
return x * f;
}
int n, c1[N << 1], c2[N << 1], ty[N], sp, tx[N], tot, tz[N];
char s[N];
void Insert(int x, int k, int c[]) {
x += N;
for (int i = x; i <= 2000001; i += i & (-i)) c[i] += k;
}
int Query(int x, int c[]) {
x += N;
int ans = 0;
for (int i = x; i; i -= i & (-i)) ans += c[i];
return ans;
}
int main() {
n = read();
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
if (s[1] == 'A') {
int a = read(), b = read(), c = read();
if (a == 0) {
if (b > c) {
sp++, ty[++tot] = (1 << 30);
}
else ty[++tot] = -(1 << 30);
}
else if(a < 0) {// x < (c - b) / a
tx[++tot] = (ceil)((c * 1.0 - b) / a), ty[tot] = 2;
if (tx[tot] > 1e6) sp++, ty[tot] = (1 << 30);
else if(tx[tot] < -1e6) ty[tot] = -(1 << 30);
else Insert(tx[tot], 1, c2);
}
else {
tx[++tot] = (floor)((c * 1.0 - b) / a), ty[tot] = 1;//// x > (c - b) / a
if (tx[tot] > 1e6) ty[tot] = -(1 << 30);
else if(tx[tot] < -1e6) ty[tot] = (1 << 30), sp++;
else Insert(tx[tot], 1, c1);
}
}
else if (s[1] == 'D') {
int x = read();
if (tz[x]) continue;
tz[x] = 1;
if (ty[x] == (1 << 30)) sp--;
else if(ty[x] == 1) Insert(tx[x], -1, c1);
else if(ty[x] == 2) Insert(tx[x], -1, c2);
}
else {
int x = read();
printf("%d\n", sp + Query(x - 1, c1) + Query(1e6, c2) - Query(x, c2));
}
}
return 0;
}