一些神仙题

Posted zzy2005

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些神仙题相关的知识,希望对你有一定的参考价值。

灭虫

题目链接
【问题描述】
你需要在一条无限长的道路上喷洒杀虫剂。
在这条道路上,总共有 N 个投放点,其中第 i 个投放点在数轴上坐标 pi 处。在每一
个投放点,你可以选择往左喷洒或往右喷洒。但是由于风向和地理环境的影响,向左喷洒和
向右喷洒的效果不一定相同。具体来说,在一个位置向左喷洒,可以覆盖 [pi - li, pi] 这一段
区域,而向右喷洒可以覆盖 [pi, pi + ri] 这一段区域。
请你决定每个投放点是向左喷洒还是向右喷洒,来使得被杀虫剂覆盖的路段长度和最大。
【输入】
第一行 N。
接下来 N 行,每行 pi, li, ri。
【输出】
输出最大的被杀虫剂覆盖的长度和。

Input Output
4
1 2 2
3 3 3
4 3 3
6 2 2
Output
9

样例说明
让第一个和第三个投放点向左喷洒,其他投放点向右喷洒。
这样能覆盖的区域是 [-1,8],总长度为 9。
【数据说明】
对于测试点 1、 2, N≤ 15;
对于测试点 3、 4, N≤ 3,000, ri = 0;
对于测试点 5、 6, N≤ 30;
对于测试点 7、 8, N≤ 300;
对于测试点 9、 10, N≤ 3,000;
保证 pi, li, ri ≤ 10^9。
Code

#include<bits/stdc++.h>
using namespace std;
const int N = 3010, inf = 1e9 + 7;
int n;
struct node 
    int p, l, r;
    bool operator < (const node &z) const 
        return p < z.p;
    
 a[N];
int b[N * 3], tot, f[N][N * 3], id[N * 3];
int main() 
    //freopen("kill.in", "r", stdin);
    //freopen("kill.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) 
        scanf("%d%d%d", &a[i].p, &a[i].l, &a[i].r);
        a[i].l = a[i].p - a[i].l; a[i].r = a[i].p + a[i].r;
        b[++tot] = a[i].p; b[++tot] = a[i].l; b[++tot] = a[i].r;
    
    sort(b + 1, b + 1 + tot); tot = unique(b + 1, b + 1 + tot) - b - 1;
    sort(a + 1, a + 1 + n);
    for (int i = 1; i <= n; i++) 
        a[i].p = lower_bound(b + 1, b + 1 + tot, a[i].p) - b;
        a[i].l = lower_bound(b + 1, b + 1 + tot, a[i].l) - b;
        a[i].r = lower_bound(b + 1, b + 1 + tot, a[i].r) - b;
        id[a[i].p] = i;
    
    //f[i][j]表示前i个区间,贡献最右点小于等于j
    for (int i = 1; i <= n; i++) 
        for (int j = 1; j <= tot; j++) f[i][j] = f[i - 1][j];
        for (int j = a[i].l + 1; j <= a[i].p; j++) 
            f[i][j] = max(f[i][j], f[i][j - 1] + b[j] - b[j - 1]);
        //i区间贡献(k,j]
        int mx = f[i - 1][a[i].p];
        for (int j = a[i].p + 1; j <= a[i].r; j++) 
            f[i][j] = max(f[i][j], mx + b[j] - b[a[i].p]);
            //i区间贡献(a[i].p,j]
            if (id[j] && a[id[j]].l < a[i].p) mx = max(mx, f[i - 1][a[id[j]].l] + b[a[i].p] - b[a[id[j]].l]);
            //相交
        
        for (int j = 2; j <= tot; j++) f[i][j] = max(f[i][j], f[i][j - 1]);
    
    printf("%d\n", f[n][tot]);
    return 0;
 

以上是关于一些神仙题的主要内容,如果未能解决你的问题,请参考以下文章

神仙dcx出的一道题

神仙题

Codeforces 1136F Cooperative Game (神仙题)

0916-模拟赛

神仙打架:PostgreSQL和MySQL谁武艺超群?

Golang | 既是接口又是类型,interface是什么神仙用法?