寒假思维训练计划Day5

持之以恒, "广积粮,缓称王", 每天进步一点点。


做了十几道构造题稍微总结一下:

1、前后缀贪心,比如说观察前后缀的sum,去看以后怎么考虑最好。Problem - 1903C - Codeforces

2、双指针贪心法,考虑两端相消或者相互作用,还有就是考虑左右边界。   Problem - 1891C - Codeforces

Problem - 1907D - Codeforces

3、转换观察法,有些关系可以抽象成图,观察图的某些性质去总结规律。也可以抽象成一个集合,两个集合相等可以说明有解可构造。Problem - 1891C - Codeforces

4、打表找规律,一般没什么规律可循即可打表找规律,一般和数论有关的很喜欢考,acm也喜欢考,属于人类智慧题。Problem - 1916D - Codeforces

5、公式推导演算,常见的分为公式的等价变形、公式的化简(这个常考,一般需要先证明某些性质,可以直接抵消,一般如果原公式处理起来很复杂时就可以考虑)。Problem - 1889B - Codeforces

6、考虑奇偶数去简化问题或者分类问题,从其中的一些运算性质入手,因为奇数偶数的加减以及%运算(这个结论很重要)的结果的奇偶性是固定的,Problem - 1898C - Codeforces

7、根据性质构造模型,看看能不能分成几个块,几个不同的集合,再选择算法去解决。Problem - 1873G - Codeforces

8、考虑从小到大处理,或者是从大到小处理,有时候先处理小的对大的不会有影响,或者反过来,这样的处理顺序是最完美的。Problem - 1904D2 - Codeforces

9、边界贪心法,一般要在问题的最边界处考虑,有时候这样做结果是最优的,或者考虑边界上的影响,假如让影响最小,就使得影响<= 固定值 。 ​​​​​​Problem - E - Codeforces and Problem - 1903C - Codeforces


Day5(思维 + 双指针贪心)Problem - D - Codeforces

题意:
给定n个区间,起始位置在0,区间的li<=ri且li>=0,ri>=0,要求按照顺序到每个区间上去,比如从起点到1区间,再从1区间到2区间...一直到n区间,一次可以跨越不超过k步,求最小的k。
题解:
最小的,而且很容易能观察出来,ans右边包括ans都是能符合条件的,ans左边都无法满足条件,具有二分的性质,然后每次到达的地方和目标区间取交集(此时维护的是一个区间,这样能覆盖所有能到达的地方,属于双指针贪心),然后往后扩展,如果是空集check失败。

代码:二分 + 双指针贪心。

#include 
#define int long long 
using namespace std; 
const int N = 2e5 + 10; 
int n, m; 
int L[N], R[N];

bool check(int mid) {
    int l = 0, r = 0; 
    for(int i = 1; i <= n; i ++ ) {
        int can_go_l = l - mid, can_go_r = r + mid;
        int use_l = max(can_go_l, L[i]), use_r = min(can_go_r, R[i]); 
        if(use_l > use_r) return 0; 
        l = use_l, r = use_r;
    }
    return 1; 
}
void solve() {
    cin >> n; 
    for(int i = 1; i <= n; i ++ ) cin >> L[i] >> R[i]; 
    int l = 0, r = 1e9 + 2;
    while(l < r) {
        int mid = l + r >> 1; 
        if(check(mid)) r = mid; 
        else l = mid + 1; 
    }
    cout << l << endl; 
    
}
signed main() {
    int ts; 
    cin >> ts;
    while(ts--) solve(); 
    
    return 0;
}

你可能感兴趣的:(算法,数据结构)