CF1732D2 Balance (Hard version) 题解

前天打了波CF结果怒掉100分,果然退化得太厉害了,遂于昨晚补题.

题面

维护一个集合 SS ,有三种操作:插入一个数、删除一个数、查询 kk 的倍数中没出现过的最小的数。

思路

考试的时候想了一个瞎jb倍增的做法,结果显然是错的(悲)
赛后想了个貌似复杂度不对的算法(能过就行,甚至还比大部分人快).
就是对每一个数x,在询问它的时候更新与x对应的一个集合exist(用map实现),这个集合维护已经在当前插入的数中(记为S)有的x的倍数(但是这个貌似根本只需要一个vector就行了,因为保证他有序)
对于一个x,查询的mex要不然在比之前exist中最大的元素大的最小的那一个里面,要不然就在被删除的exist元素中,逐一对比即可.

D.cpp
#include <cmath>
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <set>
#define int long long

#define PRINT_SET(x) \
cout<<"SET_VALUE:"<<endl;\
for(set<int>::iterator i=x.begin();i!=x.end();++i) \
cout<<*i<<' ';\
cout<<endl<<"END"<<endl;

using namespace std;
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
inline void write(int a)
{
    if (a < 0)
    {
        putchar('-');
        putchar('1');
    }
    else
    {
        if (a >= 10)
            write(a / 10);
        putchar(a % 10 + '0');
    }
}
const int maxn = 100005, mod = 998244353;
int q;
set<int> S, del;
map<int, set<int>> exist;
signed main()
{
    /* freopen("D.out","w",stdout); */
    S.insert(0);
    q = read();
    while (q--)
    {
        /* cout<<"S"<<endl;
        PRINT_SET(S);
        cout<<"del"<<endl;
        PRINT_SET(del); */
        char ch;
        cin >> ch;
        int x = read();
        if (ch == '+')
        {
            S.insert(x);
            if (del.find(x) != del.end())
            {
                del.erase(x);
            }
        }
        else if (ch == '-')
        {
            del.insert(x);
            S.erase(x);
        }
        else
        {
            int res = 0, flag = 0;
            set<int> &ex = exist[x];
            set<int>::iterator ex_i = ex.begin(), exend = ex.end();
            set<int>::iterator del_i = del.begin(), delend = del.end();
            while (ex_i != exend && del_i != delend)
            {
                ex_i = ex.lower_bound(*del_i);
                if (ex_i != exend && *ex_i == *del_i)
                {
                    res = *ex_i;
                    /* ex.erase(res); */
                    flag = 1;
                    break;
                }
                del_i = del.lower_bound(*ex_i);
            }
            if (flag)
            {
                write(res), puts("");
                continue;
            }
            int maxx=0;
            if(!ex.empty())
                maxx=*ex.rbegin()+x;
            
            set<int>::iterator Send = S.end();
            for(int i=maxx;;i+=x)
            {
                if(S.find(i)==Send)
                {
                    res=i;
                    break;
                }
                else
                {
                    ex.insert(i);
                }
            }

            write(res), puts("");
        }
    }
    return 0;
}
/*
3
+ 1
- 1
? 2
*/
/*
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
? 2
- 1
- 3
- 6 
+ 6
? 2
- 6
? 2
*/

看起来确实可以用vector,常数--

D.cpp
#include <cmath>
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#define int long long

#define PRINT_SET(x)                                          \
    cout << "SET_VALUE:" << endl;                             \
    for (set<int>::iterator i = x.begin(); i != x.end(); ++i) \
        cout << *i << ' ';                                    \
    cout << endl                                              \
         << "END" << endl;

using namespace std;
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
inline void write(int a)
{
    if (a < 0)
    {
        putchar('-');
        putchar('1');
    }
    else
    {
        if (a >= 10)
            write(a / 10);
        putchar(a % 10 + '0');
    }
}
const int maxn = 100005, mod = 998244353;
int q;
set<int> S, del;
map<int, vector<int>> exist;
signed main()
{
    /* freopen("D.out","w",stdout); */
    S.insert(0);
    q = read();
    while (q--)
    {
        /* cout<<"S"<<endl;
        PRINT_SET(S);
        cout<<"del"<<endl;
        PRINT_SET(del); */
        char ch;
        cin >> ch;
        int x = read();
        if (ch == '+')
        {
            S.insert(x);
            if (del.find(x) != del.end())
            {
                del.erase(x);
            }
        }
        else if (ch == '-')
        {
            del.insert(x);
            S.erase(x);
        }
        else
        {
            int res = 0, flag = 0;
            vector<int> &ex = exist[x];
            vector<int>::iterator ex_i = ex.begin(), exend = ex.end();
            set<int>::iterator del_i = del.begin(), delend = del.end();
            while (ex_i != exend && del_i != delend)
            {
                ex_i = lower_bound(ex_i, exend, *del_i);
                if (ex_i != exend && *ex_i == *del_i)
                {
                    res = *ex_i;
                    /* ex.erase(res); */
                    flag = 1;
                    break;
                }
                del_i = del.lower_bound(*ex_i);
            }
            if (flag)
            {
                write(res), puts("");
                continue;
            }
            int maxx = 0;
            if (!ex.empty())
                maxx = *ex.rbegin() + x;

            set<int>::iterator Send = S.end();
            for (int i = maxx;; i += x)
            {
                if (S.find(i) == Send)
                {
                    res = i;
                    break;
                }
                else
                {
                    ex.insert(ex.end(),i);
                }
            }

            write(res), puts("");
        }
    }
    return 0;
}
/*
3
+ 1
- 1
? 2
*/
/*
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
? 2
- 1
- 3
- 6
+ 6
? 2
- 6
? 2
*/
posted @ 2022-10-25 11:30  520Enterprise  阅读(154)  评论(0编辑  收藏  举报