惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
有赞技术团队
有赞技术团队
博客园 - 三生石上(FineUI控件)
博客园_首页
博客园 - 【当耐特】
WordPress大学
WordPress大学
月光博客
月光博客
博客园 - 叶小钗
S
SegmentFault 最新的问题
雷峰网
雷峰网
H
Help Net Security
宝玉的分享
宝玉的分享
A
About on SuperTechFans
IT之家
IT之家
J
Java Code Geeks
Hugging Face - Blog
Hugging Face - Blog
D
DataBreaches.Net
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 聂微东
T
The Blog of Author Tim Ferriss
B
Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog

某岛

AtCoder Beginner Contest 409 Luogu P5325. 【模板】Min_25 筛 UOJ #188. 【UR #13】Sanrd AtCoder Beginner Contest 371 AtCoder Beginner Contest 369 RPGMaker 2k3 百科 OneShot 的考古 2024“开创拓芯”游戏创享节的相关记录 CJ 回来后的戒断反应 Luogu P10221. [省选联考 2024] 重塑时光 Luogu P5308 [COCI2018-2019#4] Akvizna wqs 二分 歌唱王国 Lean 相关 BZOJ 3153. Sone1 The 2023 ICPC World Finals Luxor 新巴别塔 Sora 的想象与思考 Facebook Hacker Cup 2023 Round 1 AtCoder Beginner Contest 322 LLaMA 2 相关 HuggingFace AI Game Jam ACL 2023 Trans 相关… Luogu P2053. [SCOI2007] 修车 Luogu P1973. [NOI2011] NOI 嘉年华 Luogu P1933. [NOI2010] 旅行路线 Luogu P1954. [NOI2010] 航空管制 Luogu P2048. [NOI2010] 超级钢琴 Luogu P2046. [NOI2010] 海拔
Codeforces Round #850
2023-02-07 · via 某岛

Problem A. Monsters (easy version)

易知,最后一定是消成 [1,2,…,b] 这样的情况,然后一次连锁操作全部删除(好像炉石里有张类似的卡)。
对于只需要处理一次询问的情况,我们可以直接对 a 数组进行排序,然后贪心得到最后的 b 即可。

const int N = int(2e5) + 9;
int a[N];
int n;

int main(){

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

	Rush {
        RD(n); REP(i, n) RD(a[i]);
        LL s = 0, b = 0; sort(a, a+n);
        REP(i, n) if (a[i] > b) s += a[i] - ++b;
        cout << s << endl;
	}
}

Problem B. Letter Exchange

分情况讨论,贪心一下即可(证明感觉可以类比排列的循环分解)。

Problem C. Monsters (hard version)

第一想法,虽然现在无法排序了,但是总能用平衡树去维护的,又因为 a 的值域很小,因此用线段树或者树状数组一定会是更好的选择,具体需要维护什么,需要进一步分析。

每次加入一个新的数,我们依然需要分情况讨论,第一种是 a[i] > b 的情况,那么依然可以 ++b。
第二种 a[i] <= b 的情况,这种情况看起来比较复杂,我们需要找一个数进行替换,并重新调整当前的答案。
but wait… a[i] <= b 的情况,b 就一定不会增加了吗?

答案是否定的,比如我们看 1,1 和 2,1 … 在第二轮,虽然 1 都满足 a[i] <= b,但是前者 b 不会被更新,而后者 b 依然要更新。
因此我们发现这里用 a[i] > b 当做判定条件并不是最合适的。

事实上我们有更强的条件,每一轮次我们线段树的内部都是在和 [1,2,…,b] 这个序列进行比较,并且时刻要保证它的每个前缀不能比较的时候使用了更多的数,
所以我们可以将线段树初始化为 [-1, -1, -1, …, -1],然后保证任意时刻前缀和 <= 0 即可,也就是支持:

  1. 单点修改。
  2. 查询前缀和最早 > 0 的位置。

这个查询出的位置,就是上面所说的被替换出的数,我们用它调整答案即可。
(这个操作似乎也是可以树状数组的,我不会 >_<。)

这个做法和前几天 Universal Cup 的 E 题很像。

const int N = int(2e5) + 9;
int a[N];
int n;
 
int ss[4*N], mx[4*N];
 
#define lx (x<<1)
#define rx (lx|1)
#define ml ((l+r)>>1)
#define mr (ml+1)
#define lc lx,l,ml
#define rc rx,mr,r
#define rt 1,1,n
 
void upd(int x) {
    ss[x] = ss[lx] + ss[rx];
    mx[x] = max(mx[lx], ss[lx] + mx[rx]);
}
 
void Build(int x, int l, int r) {
    ss[x] = mx[x] = -1;
    if (l < r) {
        Build(lc); Build(rc);
        upd(x);
    }
}
 
int Query(int x, int l, int r, int k) {
    if (l == r) return l;
    return mx[lx] > k ? Query(lc, k) : Query(rc, k-ss[lx]);
}
 
void Add(int x, int l, int r, int a, int d) {
    if (l == r) {
        ss[x] += d; mx[x] += d;
    } else {
        if (a < mr) Add(lc, a, d);
        else Add(rc, a, d);
        upd(x);
    }
}
 
int main(){
 
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
 
	Rush {
        RD(n); Build(rt); LL s = 0; int b = 0;
        REP(i, n) {
            int a; s += RD(a); Add(rt, a, 1);
            if (mx[1] <= 0) {
                s -= ++b;
            } else {
                int x = Query(rt, 0);
                Add(rt, x, -1);
                s -= x;
            }
            printf("%lld ", s);
        }
        puts("");
	}
}
 
// 单点修改
// 查询前缀和最早 > 0 的位置

Posted by xiaodao
Category: 日常