《算法竞赛进阶指南》0.3前缀与差分

99. 激光炸弹

一种新型的激光炸弹,可以摧毁一个边长为 R的正方形内的所有的目标。

现在地图上有 N个目标,用整数Xi,Yi表示目标在地图上的位置,每个目标都有一个价值Wi。

激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个边长为 R
的正方形的边必须和x,y轴平行。

若目标位于爆破正方形的边上,该目标不会被摧毁。

求一颗炸弹最多能炸掉地图上总价值为多少的目标。

输入格式
第一行输入正整数 N和 R,分别代表地图上的目标数目和正方形的边长,数据用空格隔开。

接下来N行,每行输入一组数据,每组数据包括三个整数Xi,Yi,Wi,分别代表目标的x坐标,y坐标和价值,数据用空格隔开。

输出格式
输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。

数据范围
0<N≤10000,
0≤Xi,Yi≤5000

输入样例:
2 1
0 0 1
1 1 1

输出样例:
1

#include <iostream>

using namespace std;

const int N = 5010;

int g[N][N];

int main()
{
    int N, R;
    cin >> N >> R;
    int n = R, m = R; //判断边界
    for(int i = 0, x, y, w; i < N; i++)
    {
        cin >> x >> y >> w;
        x++, y++;
        n = max(n, x), m = max(m, y); 
        g[x][y] += w;
    }
    
    //求前缀和
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            g[i][j] += g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];//加了两次,减一次
            
    int res = 0;
    for(int i = R; i <= n; i++)
        for(int j = R; j <= m; j++)
            res = max(res, g[i][j] - g[i - R][j] - g[i][j - R] + g[i - R][j - R]);
        
    cout << res << endl;
    return 0;
}

100. IncDec序列

给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间 [l,r],使下标在这个区间内的数都加一或者都减一。

求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。

输入格式
第一行输入正整数n。

接下来n行,每行输入一个整数,第i+1行的整数代表ai。

输出格式
第一行输出最少操作次数。
第二行输出最终能得到多少种结果。

数据范围
0<n≤105,
0≤ai<2147483648

输入样例:
4
1
1
2
2

输出样例:
1
2

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 100010;

int a[N];

int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <=n; i++) cin >> a[i];
    for(int i = n; i > 1; i--) a[i] -= a[i - 1];
    
    LL pos = 0, neg = 0; // 差分序列中正数之和pos,负数之和neg
    for(int i = 2; i <= n; i++)
        if(a[i] > 0) pos += a[i];
        else neg -= a[i];
        
    cout << min(pos, neg) + abs(pos - neg) << endl;
    cout << abs(pos - neg) + 1;
}

101. 最高的牛

有 N头牛站成一行,被编队为1、2、3…N,每头牛的身高都为整数。
当且仅当两头牛中间的牛身高都比它们矮时,两头牛方可看到对方。
现在,我们只知道其中最高的牛是第 P头,它的身高是 H,剩余牛的身高未知。

但是,我们还知道这群牛之中存在着 M对关系,每对关系都指明了某两头牛 A 和 B可以相互看见。
求每头牛的身高的最大可能值是多少。

输入格式
第一行输入整数N,P,H,M,数据用空格隔开。
接下来M行,每行输出两个整数 A和 B ,代表牛 A 和牛 B可以相互看见,数据用空格隔开。

输出格式
一共输出 N行数据,每行输出一个整数。
第 i行输出的整数代表第 i头牛可能的最大身高。

数据范围
1≤N≤10000,
1≤H≤1000000,
1≤A,B≤10000,
0≤M≤10000

输入样例:
9 3 5 5
1 3
5 3
4 3
3 7
9 8

输出样例:
5
4
5
3
4
4
5
5
5

注意:此题中给出的关系对可能存在重复

#include <iostream>
#include <set>

using namespace std;

const int N = 10010;

int height[N];

int main()
{
    int n, p, h, m;
    cin >> n >> p >> h >> m;
    height[1] = h;
    set<pair<int, int>> existed;
    for(int i = 0, a, b; i < m; i++)
    {
        cin >> a >> b;
        if(a > b) swap(a, b);
        if(!existed.count({a, b})) //a,b
        {
            existed.insert({a, b});
            height[a + 1] --, height[b] ++;
        }
    }
    for(int i = 1; i <=n; i++)
    {
        height[i] += height[i - 1];
        cout << height[i] << endl;
    }
    return 0;
}
posted @ 2019-05-10 10:32  WMXNLFD  阅读(165)  评论(0编辑  收藏  举报