首页 > 其他分享 >Codeforces 799E Aquarium decoration

Codeforces 799E Aquarium decoration

时间:2024-02-22 21:46:06浏览次数:32  
标签:cnt 799E int maxp Codeforces back decoration maxn ls

考虑去枚举能满足 \(1, 2\) 的个数 \(l\),那自然只能满足 \(1\) 或 \(2\) 的个数为 \(\max\{k - l, 0\}\)。
对于还剩下的,可以从只能满足 \(1, 2\) 和不能满足任意一个的选出来。
显然如果要选就是选最小的。

考虑用个数据结构优化这个过程。
查询前 \(k\) 大的和,插入一个数,可以想到用值域线段树。
对于一开始就可以把都不能满足的插入线段树。
\(k\) 递增,\(\max\{k - l, 0\}\) 递减,于是可以依次取出只能满足 \(1\) 或 \(2\) 两个序列中分别的最大值,然后放入线段树中并从序列中删除,因为其肯定不可能再在只能满足 \(1\) 个的里面出现了。

注意一些边界情况。

时间复杂度 \(O(n\log V)\)。

#include<bits/stdc++.h>
using i64 = long long;
const i64 inf = LLONG_MAX;
const int maxn = 2e5 + 10, maxp = maxn * 31;
i64 sum[maxp]; int cnt[maxp], ls[maxp], rs[maxp], tot, rt;
void add(int &k, int x, int l = 1, int r = 1e9) {
    if (! k) k = ++tot;
    cnt[k]++, sum[k] += x;
    if (l == r) return ;
    int mid = (l + r) >> 1;
    x <= mid ? add(ls[k], x, l, mid) : add(rs[k], x, mid + 1, r);
}
i64 qry(int k, int x, int l = 1, int r = 1e9) {
    if (l == r) return 1ll * l * x;
    int mid = (l + r) >> 1;
    return cnt[ls[k]] < x ? (sum[ls[k]] + qry(rs[k], x - cnt[ls[k]], mid + 1, r)) : qry(ls[k], x, l, mid);
}
std::vector<int> a[4];
int A[maxn], b[maxn];
int main() {
    int n, m, k; scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= n; i++) scanf("%d", &A[i]);
    int p; scanf("%d", &p);
    while (p--) {int x; scanf("%d", &x); b[x] |= 1;}
    scanf("%d", &p);
    while (p--) {int x; scanf("%d", &x); b[x] |= 2;}
    for (int i = 1; i <= n; i++) a[b[i]].push_back(A[i]);
    for (int i = 0; i < 4; i++) std::sort(a[i].begin(), a[i].end());
    for (int x : a[0]) add(rt, x);
    int l = std::max({0, k - int(a[1].size()), k - int(a[2].size())});
    i64 sum1 = 0, sum2 = 0;
    for (i64 x : a[1]) sum1 += x;
    for (i64 x : a[2]) sum2 += x;
    i64 ans = inf, sum3 = 0;
    if (l > a[3].size()) return puts("-1"), 0;
    for (int i = 0; i < l; i++) sum3 += a[3][i];
    while (l <= m && l <= a[3].size()) {
        int p = std::max(k - l, 0);
        while (a[1].size() > p) add(rt, a[1].back()), sum1 -= a[1].back(), a[1].pop_back();
        while (a[2].size() > p) add(rt, a[2].back()), sum2 -= a[2].back(), a[2].pop_back();
        if (l + p + p <= m) ans = std::min(ans, sum1 + sum2 + sum3 + qry(rt, m - l - p - p));
        if (l == a[3].size()) break;
        sum3 += a[3][l++];
    }
    printf("%lld\n", ans == inf ? -1 : ans);
    return 0;
}

标签:cnt,799E,int,maxp,Codeforces,back,decoration,maxn,ls
From: https://www.cnblogs.com/rizynvu/p/18028272

相关文章

  • Codeforces 图论题
    CF243BHydra枚举点\(u,v\),或者说枚举边。然后找出\(u,v\)分别所连的点。有数组\(st\),结点\(x\)仅与\(u\)相邻则\(st[x]=1\),仅与\(v\)相邻则\(st[x]=2\),与两个点都相邻则\(st[x]=3\)。用数组\(rest\)记录\(st[x]=3\)的所有\(x\)。先优先选走至多\(h\)个\(......
  • Codeforces 869D The Overdosing Ubiquity
    考虑树的\(\text{dfs}\)(根据当前节点\(u\)找到\(v\)满足存在\((u,v)\),然后走向\(v\)进入更深的搜索)为和能做到\(O(n)\)的复杂度。原因是没有环的情况,到每个点只有一条路径。回到这个题,有\(m\)条边导致到每个点可能有多条路径了。能发现其实还是能\(\text{dfs}\)......
  • Codeforces 1876F - Indefinite Clownfish
    首先注意到这样一个性质:既然两个序列的平均值相同,并且又形成公差\(\pm1\)的等差数列,就必然会存在一个元素\(x\)满足\(x\)在两个序列中都出现过(否则两个序列的值域区间不交,值域区间靠后的那个显然平均值比靠前的那个大)。那么我们枚举\(x\)在两个序列中出现的位置\(p\)和......
  • Codeforces Round 923 (Div. 3)
    A.MakeitWhite#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=longlong;usingi128=__int128;usingldb=longdouble;#defineinti64usingvi=vector<int>;usingpii=pair<int,int>;usingvii......
  • Codeforces Round 928 (Div. 4)
    CodeforcesRound928(Div.4)比赛链接A.VladandtheBestofFive思路就是统计字符A和字符B的个数,将个数多的那个输出出来Code#include<bits/stdc++.h>usingnamespacestd;#defineall(x)x.begin()+1,x.end()#defineintlonglongvoidsolve(){strings;......
  • Codeforces 1806E Tree Master
    考虑一个最基础的暴力,就是直接记忆化搜索暴力往上跳。但是能发现如果一层的节点数过多,状态数太多,就寄了。再考虑一个基础的暴力,就是直接跳。但是如果要跳的层数过多,就寄了。考虑结合一下,根号分治。对于一层内节点数\(\le\sqrt{n}\)的记录下每两个点间的答案。对于节点数......
  • Codeforces Round 928(Div. 4)
    Dashboard-CodeforcesRound928(Div.4)-Codeforces第一次参加CF,最后一道题连题都没读,下次不会就跳,菜是原罪A:找字符串中A,B数量,遍历一下最后比较即可B:判断是三角形还是正方形,题目表示除了正方形就是三角形,所以直接判断是不是正方形,用ans数组记录每一行1的个数,然后从大......
  • Codeforces Round 900 (Div. 3)
    题目A.只要k出现过就是YES#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e5+10;#defineinf0x3f3f3f3fvoidsolve(){intn,k;cin>>n>>k;map<int,int>mp;for(inti=0,x;i<n;i++){cin......
  • Codeforces Round 928 (Div. 4) (小白的复盘)
    A.VladandtheBestofFive思路:给你一个长度字符串只包含A和B输出最多的字符解法:按题意来Code:#include<bits/stdc++.h>usingnamespacestd;intmain(){intt;cin>>t;while(t--){strings;cin>>s;intcnt=0;fo......
  • Codeforces Round 928 (Div. 4)(A、B、C、D、E、G)
    目录ABCDEGA统计A、B输出#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(inti=(a);i>=(b);--i)#definepiipair<int,int>#definelllonglong#definedbdouble#de......