Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code

题目链接

题意:

给出\(n\)个俄罗斯套娃,每个套娃都有一个\(in_i,out_i\),并满足\(out_i>in_i\)。定义套娃\(i\)能套在套娃\(j\)里面,当且仅当\(out_i\leq in_j\)。

定义极大套娃组:当且仅当不能有另外一个套娃套在它们身上。

定义套娃组额外空间为\(in_1+(in_2-out_1)+\cdots +(in_k-out_{k-1})\),其中\(k\)为最大的那个套娃。

现在求额外空间最小的极大套娃组都多少个。

思路:

将上面求和式子变换一下有:

\[in_k+\sum_{i=1}^{k-1}in_i-out_i
\]

分析这个式子,也就是对于一个在最外面的套娃\(k\)来说,其余里面套娃的贡献就为\(in_i-out_i\),是独立的。

首先将所有套娃按\(in\)升序排序,之后依次枚举每一个套娃并将其视作最后一个套娃。假设当前枚举的\(i\),那么\(dp(i)=min_{out_j\leq in_i}\{dp(j)\}+in_i\),\(dp\)中存储的是套娃的贡献值,\(dp(i)\)表示以\(i\)作结尾的套娃最小的额外空间是多少。

因为题目还要求数目,考虑转移的时候在线段树上面查询,同时维护一个\(sum\)记录个数,查询、更新的时候进行结点的合并,合并实现两个功能:一是找最小值,而是更新个数,详见代码即可。

最后统计答案的时候,找到所有的极大套娃组进行统计。

代码如下:

#include <bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 2e5 + 5, MOD = 1e9 + 7;
int n;
pii a[N];
struct SEG{
struct node{
ll Min, sum;
node() {
sum = 0; Min = INF;
}
node(ll Min, ll sum) : Min(Min), sum(sum) {}
node operator + (const node &other) const {
node res = node();
if(Min < other.Min) {
res.Min = Min;
res.sum = sum;
} else if(Min == other.Min) {
res.Min = Min;
res.sum = (other.sum + sum) % MOD;
} else {
res.Min = other.Min;
res.sum = other.sum;
}
return res;
}
}t[N << 3], res;
void build(int o, int l, int r) {
if(l == r) {
t[o] = node();
return;
}
int mid = (l + r) >> 1;
build(o << 1, l, mid); build(o << 1|1, mid + 1, r);
}
void update(int o, int l, int r, int p, node v) {
if(l == r) {
t[o] = t[o] + v;
return ;
}
int mid = (l + r) >> 1;
if(p <= mid) update(o << 1, l, mid, p, v);
else update(o << 1|1, mid + 1, r, p, v);
t[o] = t[o << 1] + t[o << 1|1];
}
void query(int o, int l, int r, int L, int R) {
if(L <= l && r <= R) {
res = res + t[o];
return ;
}
int mid = (l + r) >> 1;
if(L <= mid) query(o << 1, l, mid, L, R);
if(R > mid) query(o << 1|1, mid + 1, r, L, R);
}
}seg;
int D, b[N << 1];
ll c[N], d[N];
int id(int x) {
return lower_bound(b + 1, b + D + 1, x) - b;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i].se >> a[i].fi;
b[++D] = a[i].fi; b[++D] = a[i].se;
}
sort(a + 1, a + n + 1);
sort(b + 1, b + D + 1);
D = unique(b + 1, b + D + 1) - b - 1;
ll Min = INF;
seg.build(1, 1, D);
for(int i = 1; i <= n; i++) {
seg.res = SEG::node();
seg.query(1, 1, D, 1, id(a[i].fi));
if(seg.res.Min == INF) {
seg.res = SEG::node(a[i].fi - a[i].se, 1);
c[i] = 1; d[i] = a[i].fi;
seg.update(1, 1, D, id(a[i].se), seg.res);
} else {
c[i] = seg.res.sum;
d[i] = seg.res.Min + a[i].fi;
seg.res.Min += a[i].fi - a[i].se;
seg.update(1, 1, D, id(a[i].se), seg.res);
}
if(a[i].se > a[n].fi) Min = min(Min, d[i]);
}
ll ans = 0;
for(int i = 1; i <= n; i++)
if(a[i].se > a[n].fi && d[i] == Min)
ans = (ans + c[i]) % MOD;
cout << ans;
return 0;
}

Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code的更多相关文章

  1. Educational Codeforces Round 69 (Rated for Div. 2)

                                                                                                  A. DIY ...

  2. Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 背包dp

    D. Yet Another Subarray Problem You are given an array \(a_1, a_2, \dots , a_n\) and two integers \( ...

  3. Educational Codeforces Round 69 (Rated for Div. 2) C. Array Splitting 水题

    C. Array Splitting You are given a sorted array

  4. Educational Codeforces Round 69 (Rated for Div. 2) A~D Sloution

    A. DIY Wooden Ladder 题意:有一些不能切的木板,每个都有一个长度,要做一个梯子,求梯子的最大台阶数 做梯子的木板分为两种,两边的两条木板和中间的若干条台阶木板 台阶数为 $k$ 的 ...

  5. Educational Codeforces Round 69 (Rated for Div. 2)D(DP,思维)

    #include<bits/stdc++.h>using namespace std;int a[300007];long long sum[300007],tmp[300007],mx[ ...

  6. Educational Codeforces Round 69 (Rated for Div. 2) C. Array Splitting (思维)

    题意:给你一个长度为\(n\)的升序序列,将这个序列分成\(k\)段,每一段的值为最大值和最小值的差,求\(k\)段值的最小和. 题解:其实每一段的最大值和最小值的差,其实就是这段元素的差分和,因为是 ...

  7. Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 【数学+分块】

    一.题目 D. Yet Another Subarray Problem 二.分析 公式的推导时参考的洛谷聚聚们的推导 重点是公式的推导,推导出公式后,分块是很容易想的.但是很容易写炸. 1 有些地方 ...

  8. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  9. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

随机推荐

  1. 学Redis这篇就够了!

    学Redis这篇就够了!   作者:王爷科技 https://www.toutiao.com/i6713520017595433485 Redis 简介 & 优势 Redis 数据类型 发布订 ...

  2. Java注解及其原理以及分析spring注解解析源码

    注解的定义 注解是那些插入到源代码中,使用其他工具可以对其进行处理的标签. 注解不会改变程序的编译方式:Java编译器对于包含注解和不包含注解的代码会生成相同的虚拟机指令. 在Java中,注解是被当做 ...

  3. Nginx配置REWRITE隐藏index.php

    server { listen 80; server_name localhost; root D:\workspace\PHP\Atromic; location / { index index.p ...

  4. xshell怎么配置鼠标颜色

    在控制面板--> 鼠标属性 --> 指针 --> 文本选择 --> 浏览 --> beam_r.cur --> 打开 --> 应用 --> 确定

  5. 生成Makefile文件全过程

    [1]生成Makefile文件全过程 整体流程如下图: 注意:以下文件根目录为testmake(任意位置新建即可) (1)测试程序 1.1 建立两个目录:mkdir include source 1. ...

  6. my first blog by cnblogs

    #include <stdio.h> int main() { printf("hello everyone."); ; } 上面为我的第一个C语言测试代码,仅供初学者 ...

  7. 「NOI2018」冒泡排序

    「NOI2018」冒泡排序 考虑冒泡排序中一个位置上的数向左移动的步数 \(Lstep\) 为左边比它大的数的个数,向右移动的步数 \(Rstep\) 为右边比它大的数的个数,如果 \(Lstep,R ...

  8. 『线段树及扫描线算法 Atlantis』

    入门看这边『线段树 Segment Tree』. 扫描线 扫描线是一种解决一类平面内统计问题的算法,通常会借助线段树来实现,我们通过一道例题来引入这个算法. Atlantis Description ...

  9. 【C#】58. .Net中的并发集合——BlockingCollection

    https://blog.csdn.net/huiwuhuiwu/article/details/53608269 这篇是并发集合中的最后一篇,介绍一下BlockingCollection.在工作中我 ...

  10. SAP T CODE : Description (Program)

    SAP T CODE : Description (Program) V : Quickstart RKCOWUSL (RKCOWUSL)V+01 : Create Sales Call (SAPMV ...