[ABC306E] Best Performances

3次阅读
没有评论

[ABC306E] Best Performances

题目大意:

有一个长度为 n 的序列,最开始都是 0
q 个操作,改变 a[p]v。并输出前 k 大的数的和。

题目分析:

  • 可以维护两个 multiset。第一个 multiset s维护前 k 大的数,第二个 multiset t维护剩下的数。
  • 每次操作先寻找 a[p]是否在 s 中,如果在则 ans 减去 a[p], 然后删除 a[p]
  • t 加入v。接着用 t 来更新 sans。最后把 a[p] 改为 v 输出 ans

代码:

#include <bits/stdc++.h>

using namespace std;
template <typename _T>

inline void read(_T &x)
{
    x = 0; char c; _T d = 1;
    while(c > 57 || c < 48){
        c = getchar();
        if(c == '-') d = -1;
    }
    while(c >= 48 && c <= 57){
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    x *= d;
}

const int N = 5e5 + 5;
int n, k, q;
int a[N];
long long ans;
multiset<int> s;//从小到大排序
multiset<int, greater<int> > t;//从大到小排序

void update()
{
    while(s.size() < k){
        s.insert(*t.begin());
        ans += *t.begin();
        t.erase(t.begin());
    }
    while(*t.begin() > *s.begin()){
        ans = ans + *t.begin() - *s.begin();
        t.insert(*s.begin());
        s.erase(s.begin());
        s.insert(*t.begin());
        t.erase(t.begin());
    }
}

signed main()
{
    read(n), read(k), read(q);
    for(int i = 1; i <= k; i++) s.insert(0);
    for(int i = 1; i <= n - k; i++) t.insert(0);
    while(q--)
    {
        int p, v;
        read(p), read(v);

        t.insert(v);
        if(s.find(a[p]) != s.end()){
            s.erase(s.find(a[p]));
            ans -= a[p];
        }else{
            t.erase(t.find(a[p]));
        }
        a[p] = v;
        update();

        cout << ans << "\n"; 
    }

    return 0;
}
正文完
 0
评论(没有评论)