题目链接
首先,这道题首先让我认识到了边界条件的细节上的处理,于是认识了这几个函数:
向下取整 floor()
然后细讲一下题目中的各种问题,首先,“一元不等式”——题目中的定义为“x的系数可以为0”,此时直接判断"b > c"的正确性即可。
其次,很容易想到,a出了分0和非0还要分正负,接下去就是分类讨论了。
a > 0
于是有(注意这里的向下取整符号)
a < 0
于是同样的,如果我们用表示所有“a < 0”集合的元素个数,那么我们利用逆否问题的成立性来反过来就可以知道:原答案等于,其中表示原集合中x成立的个数。那么也等于(注意向上取整符号)。
好了,这时候问题就可以用两个树状数组解决了。
注意
有的人(不是谁,就是我)可能会这么写向上取整和向下取整,是错的,因为这里的值都不一定是正数,只有在正数的时候才满足这样的写法:
inline int More_UP(int a, int b, int c) { return (c - b) / a + 1; }
inline int Less_Down(int a, int b, int c) { return (b - c + a - 1) / a; }
这或许是我一开始只有30分的缘故吧呜呜呜,然后,造了两个样例,明白了其过程上的问题:
2
A -12 15 3
Q 1
ans:0
2
A -11 -15 -4
Q -1
ans:0
好了,最后的时候,上代码啦,看很多小伙伴都是看了其他题解的用特判的方式解决该问题,但是我觉得我可能想到的第一个就是离散化吧……可能没来得及看数据范围的缘故。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e5 + 7;
inline int More_UP(int a, int b, int c) { return floor(1. * (c - b) / a) + 1; }
inline int Less_Down(int a, int b, int c) { return ceil(1. * (c - b) / a); }
int Q, _UP;
int Lsan[maxN];
struct BIT_Tree
{
int tree[maxN], all;
inline void update(int x, int v)
{
while(x <= _UP)
{
tree[x] += v;
x += lowbit(x);
}
}
inline int query(int x)
{
int sum = 0;
while(x)
{
sum += tree[x];
x -= lowbit(x);
}
return sum;
}
} b[2];
int real[maxN];
struct Question
{
int op, val; //"-1":del, "0":query, "1":add, "2":add && a==0
Question(int a=0, int b=0):op(a), val(b) {}
} ques[maxN];
int Stap[maxN], Stop = 0;
bool have_del[maxN] = {false};
int main()
{
scanf("%d", &Q);
char op[10]; _UP = 0;
int flag = 0;
for(int i=1, a, b, c; i<=Q; i++)
{
scanf("%s", op);
if(op[0] == 'A')
{
scanf("%d%d%d", &a, &b, &c);
if(!a)
{
ques[i] = Question(2, b > c);
}
else
{
ques[i] = Question(1, (a > 0 ? More_UP(a, b, c) : Less_Down(a, b, c)));
Lsan[++_UP] = ques[i].val;
}
real[i] = a > 0;
}
else if(op[0] == 'D')
{
scanf("%d", &a);
ques[i] = Question(-1, a);
}
else
{
scanf("%d", &a);
ques[i] = Question(0, a);
Lsan[++_UP] = a;
}
}
sort(Lsan + 1, Lsan + _UP + 1);
_UP = (int)(unique(Lsan + 1, Lsan + _UP + 1) - Lsan - 1);
for(int i=1; i<=Q; i++)
{
if(ques[i].op == 0 || ques[i].op == 1) ques[i].val = (int)(lower_bound(Lsan + 1, Lsan + _UP + 1, ques[i].val) - Lsan);
}
b[0].all = 0;
for(int i=1, id; i<=Q; i++)
{
if(ques[i].op == 1)
{
if(real[i])
{
b[1].update(ques[i].val, 1);
}
else
{
b[0].all++;
b[0].update(ques[i].val, 1);
}
Stap[++Stop] = i;
}
else if(ques[i].op == 2)
{
flag += ques[i].val;
Stap[++Stop] = i;
}
else if(ques[i].op == -1)
{
id = Stap[ques[i].val];
if(have_del[id]) continue;
have_del[id] = true;
if(ques[id].op == 2)
{
flag -= ques[id].val;
}
else if(real[id])
{
b[1].update(ques[id].val, -1);
}
else
{
b[0].all--;
b[0].update(ques[id].val, -1);
}
}
else
{
printf("%d\n", flag + b[1].query(ques[i].val) + b[0].all - b[0].query(ques[i].val));
}
}
return 0;
}
最后最后,我要说一下,这当真是道很有趣的题目。