原题链接

2300分

大意

俄罗斯套娃,每个有内容半径in和外围半径out

in_i<out_i

如果 in_i >= out_j ,那么j可以放在i内

定义残留空间 = 一列嵌套的套娃 未使用的半径和 ,如 {1,2},{2,5},{7,9},未使用的白净和为(1-0)+(2-2)+(7-5) = 3

有效残留空间,如果 一列嵌套的套娃,还能从给出的套娃中选择一个加入这一列,那么原本的残留空间为无效值。如给{1,2},{2,3},{2,5},{7,9},只选择{1,2},{7,9}是无效的嵌套列,而选择{1,2},{2,3},{7,9}是有效的

令M = 最小的有效残留空间

求有效残留空间=M的方案数 % MOD

数据范围

套娃个数<= 200'000

半径<=1'000'000'000

MOD = 1'000'000'007

题解 翻译自官方题解

赛内我写了大概十多分钟没写出来,算法是想到n方的 但是没想到怎么优化到时间复杂度内

https://codeforces.com/blog/entry/68615

首先我们 把它们按照内半径排序in_i,

dp[i] = {x,y} 从末尾到第i个,最小的有效残留空间x, 这样的情况下的方案数 y

dp[i] = {in_i,1} 如果没有 能套在i外面的

如果有能套在i外面的j 那么

dp[i].x = min(d[j].x - (out_i-in_i)) = min(d[j].x) - (out_i-in_i)

我自己考虑漏的一点,假设 我们在尝试i了,那么min[d[ all j such in_j>=out_i ].x] 对于>=i 来说,一定是有效的,当时考虑漏了,在想怎么维护左右游标,来计算有效范围内的最小值

反证法

因为我们 要把i放在j内,如果不是有效的,

首先我们的dp定义保证了 不会插入其它在j以后

那么意味着,在i和j之间还能插入其它,假设为k

那么有d[k].x < d[j].x 和我们刚刚假设的min矛盾

综上

读入O(n)

排序O(n log n)

维护一个minx数组

每次计算dp[i] 二分>=out_i的坐标,计算完后更新minx 每次O(log n)

总共O(n log n)

代码 (Rust)

https://codeforces.com/contest/1197/submission/57928269

#![allow(unused_imports)]
use std::cmp::*;
use std::collections::*;
use std::ops::Bound::*; struct Scanner {
buffer : std::collections::VecDeque<String>
} impl Scanner { fn new() -> Scanner {
Scanner {
buffer: std::collections::VecDeque::new()
}
} fn next<T : std::str::FromStr >(&mut self) -> T { if self.buffer.len() == 0 {
let mut input = String::new();
std::io::stdin().read_line(&mut input).ok();
for word in input.split_whitespace() {
self.buffer.push_back(word.to_string())
}
} let front = self.buffer.pop_front().unwrap();
front.parse::<T>().ok().unwrap()
}
} fn main() {
const MOD:i32 = 1_000_000_007;
let mut s = Scanner::new();
let n : usize = s.next();
let mut arr:Vec<(i32,i32)> = Vec::new();
for _i in 0..n {
let out_i: i32 = s.next();
let in_i: i32 = s.next();
arr.push((in_i,out_i));
}
arr.sort();
let mut minx:BTreeMap<i32,(i32,i32)> = BTreeMap::new(); // (in>=, (mincost,cnt))
let mut ans:i32 = 0;
for i in arr.iter().rev() {
let out_i = i.1;
let in_i = i.0; // 二分找到 >= out_i 的minx
//
let bin_res:(i32,i32) = match minx.range((Included(&out_i), Unbounded)).next() {
Some(val) => *(val.1),
None => (out_i,1)
}; let cost = (bin_res.0 - (out_i - in_i), bin_res.1);
// 获取当前>=in_i 的 minx 如果没有则是 0 let cur = match minx.range((Included(&in_i), Unbounded)).next() {
Some(val) => *(val.1),
None => (cost.0,0)
}; let count = minx.entry(in_i).or_insert(cur);
if count.0 > cost.0 {
ans = cost.1;
(*count) = cost;
} else if count.0 == cost.0 {
(*count).1 += cost.1;
(*count).1 %= MOD;
ans = (*count).1;
}
// println!("{:?} {:?}", i , count);
}
println!("{}",ans );
}

总结

最近在看Rust,想说 这lower_bound 用range来写,写得我自闭,但是回过头来看

感觉用match比c++写 成lower_bound 再判断是否等于.end()更加清晰

再比如 下面

entry+or_insert这里

最开始我的两个if里分别时minx.insert和count操作,这样 连编译都通不过,因为一个变量不允许同时 两个mutable

此外 赞美一下 .0,.1相对于 c++中的 .first,.second或者说 get<0>(...),get<1>(...)

简洁而不失去意义

Codeforces 1197 E (dp+sort+二分) (Rust)的更多相关文章

  1. Codeforces 830A. Office Keys (贪心二分 or DP)

    原题链接:http://codeforces.com/contest/830/problem/A 题意:在一条数轴上分别有n个人和k把钥匙(n<=k),以及一个目的地,每个人要各自拿到一个钥匙后 ...

  2. codeforces 487B B. Strip(RMQ+二分+dp)

    题目链接: B. Strip time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  3. Codeforces 865C Gotta Go Fast 二分 + 期望dp (看题解)

    第一次看到这种骚东西, 期望还能二分的啊??? 因为存在重置的操作, 所以我们再dp的过程中有环存在. 为了消除环的影响, 我们二分dp[ 0 ][ 0 ]的值, 与通过dp得出的dp[ 0 ][ 0 ...

  4. Codeforces 749E Gosha is hunting 二分+DP

    很神奇的一题 看完题解不由惊叹 题意:$n$个神奇宝贝 $a$个普通球 $b$个高级球 普通球抓住$i$神奇宝贝的概率为$u[i]$ 高级球为$p[i]$ 一起用为$u[i]+p[i]-u[i]*p[ ...

  5. CodeForces - 847B Preparing for Merge Sort 二分

    http://codeforces.com/problemset/problem/847/B 题意:给你n个数(n<2e5)把它们分成若干组升序的子序列,一行输出一组.分的方法相当于不断找最长递 ...

  6. codeforces 459E E. Pashmak and Graph(dp+sort)

    题目链接: E. Pashmak and Graph time limit per test 1 second memory limit per test 256 megabytes input st ...

  7. codeforces 666A (DP)

    题目链接:http://codeforces.com/problemset/problem/666/A 思路:dp[i][0]表示第a[i-1]~a[i]组成的字符串是否可行,dp[i][1]表示第a ...

  8. CodeForces 377B---Preparing for the Contest(二分+贪心)

    C - Preparing for the Contest Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d ...

  9. Codeforces 484B Maximum Value(高效+二分)

    题目链接:Codeforces 484B Maximum Value 题目大意:给定一个序列,找到连个数ai和aj,ai%aj尽量大,而且ai≥aj 解题思路:类似于素数筛选法的方式,每次枚举aj,然 ...

随机推荐

  1. 错排问题 && 洛谷 P1595 信封问题

    传送门 一道裸的错排问题 错排问题 百度百科上这样说 就是对于一个排列,每一个数都不在正确的位置上的方案数.n 个元素的错排数记为 D(n). 公式 D(n)=(n−1)∗(D(n−2)+D(n−1) ...

  2. 2019牛客暑期多校训练营(第三场) - D - Big Integer - 数论

    https://ac.nowcoder.com/acm/contest/883/D \(A(n)\) 是由n个1组成的一个整数. 第一步:把 \(A(n)\) 表示为 \(\frac{10^n-1}{ ...

  3. 省流量 转:http://www.wtoutiao.com/p/T3b8it.html

    前言:“客户端上传时间戳”的玩法,你玩过么?一起聊聊时间戳的奇技淫巧! 缘起:无线时代,流量敏感.APP在登录后,往往要向服务器同步非常多的数据,很费流量,技术上有没有节省流量的方法呢?这是本文要讨论 ...

  4. vue 中使用class(样式)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. vue.js(19)--vue中子组件调用父组件的方法

    子组件是不能直接使用父组件中的方法的,需要进行事件绑定(v-on:自定义方法名="父组件方法名"),然后在子组件中再定义一个方法,使用this.$emit('自定义方法名')语句完 ...

  6. HTTPS证书转换成PEM格式

    PEM 格式的证书文件(*.pem)一般为以下格式: 注意:PEM 格式证书文件可用 notepad++ 等文本编辑器打开. CER / CRT 格式证书转换为 PEM 格式 对于 CER / CRT ...

  7. 模块学习笔记-IR2110/IR2130(上)

    引言 IR2110 / IR2113是高压,高速功率MOSFET和IGBT驱动器,具有独立的高端和低端参考输出通道.逻辑输入与标准CMOS或LSTTL输出兼容,低至3.3V逻辑.浮动通道可用于驱动高端 ...

  8. Rsync+sersync 数据同步指南

    (1):sersync 可以记录下被监听目录中发生变化的(包括增加.删除.修改)具体某一个文件或 某一个目录的名字: (2):rsync 在同步的时候,只同步发生变化的这个文件或者这个目录(每次发生变 ...

  9. centos误删除文件如何恢复

    当意识到误删除文件后,切忌千万不要再频繁写入了,否则你的数据恢复的数量将会很少. 而我们要做的是,第一时间把服务器上的服务全部停掉,直接killall 进程名 或者 kill -9 pid . 然后把 ...

  10. C# 异常处理最佳实践,解决代码分析提示CA1031:不要捕捉一般异常类型的解决办法

    异常类型 异常一般分为系统异常 和 应用异常.系统异常有无法连接数据库,而应用异常是业务逻辑异常,比如授权失败. 在 C# 中异常基于 System.Exception,派生出 System.Syst ...