[JLOI2011]不等式组【离散化+树状数组+边界条件处理好题】

题目链接


  首先,这道题首先让我认识到了边界条件的细节上的处理,于是认识了这几个函数:

向下取整 floor()

向上取整ceil()

四舍五入取整round()

  然后细讲一下题目中的各种问题,首先,“一元不等式”——题目中的定义为“x的系数可以为0”,此时直接判断"b > c"的正确性即可。

  其次,很容易想到,a出了分0和非0还要分正负,接下去就是分类讨论了。

a > 0

x > \frac{c - b}{a}于是有x \geq \left \lfloor \frac{c - b}{a} \right \rfloor + 1(注意这里的向下取整符号)

a < 0

x < \frac{c - b}{a}于是同样的,如果我们用all表示所有“a < 0”集合的元素个数,那么我们利用逆否问题的成立性来反过来就可以知道:原答案等于all - f(x \geq \frac{c - b}{a} ),其中f(x)表示原集合中x成立的个数。那么也等于all - f(x \geq\left \lceil \frac{c - b}{a} \right \rceil )(注意向上取整符号)。

  好了,这时候问题就可以用两个树状数组解决了。

注意

有的人(不是谁,就是我)可能会这么写向上取整和向下取整,是错的,因为这里的值都不一定是正数,只有在正数的时候才满足这样的写法:

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;
}

最后最后,我要说一下,这当真是道很有趣的题目。

发布了884 篇原创文章 · 获赞 1057 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/105225899