HihoCoder - 1249 Xiongnu's Land —— 差分数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lngxling/article/details/82904898

题意:

两个人分一块横坐标0~R,纵坐标无限大的土地,里面有许多矩形形状的绿洲,保证绿洲没有重叠

需要选定一个整数横坐标x,满足:

1.坐标左侧的绿洲面积大于等于右侧的绿洲面积

2.坐标左侧的面积要尽可能大

问x是多少

思路:

要满足第二个条件,只需要从R处向左找第一个满足条件的位置,问题在如何快速求出左右两侧的绿洲面积

绿洲都是矩形,假设有一个左上角坐标XY,宽度W高度H的矩形,我们可以将它看作区间[X,X+W]上值加H

然后利用差分数组,在X位置加H,在X+W+1位置减H,然后求一下前n项和就是1~i处的绿洲面积,最后遍历查找就可以了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define max_ 100010
#define mod 1000000007
#define inf 0x3f3f3f3f
int r,n;
ll num[1000100];
int main(int argc, char const *argv[]) {
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof num);
        scanf("%d%d",&r,&n);
        for(int i=1;i<=n;i++)
        {
            int x,y,w,h;
            scanf("%d%d%d%d",&x,&y,&w,&h);
            num[x]+=h;
            num[x+w]-=h;
        }
        ll sum=0;
        for(int i=1;i<=r;i++)
        {
            sum+=num[i];
            num[i]=sum+num[i-1];
        }
        int ans=-1;
        ll minn=10000000010;
        for(int i=r;i>=1;i--)
        {
            ll k1=num[i-1];
            ll k2=num[r]-num[i-1];
            if((k1>=k2)&&(k1-k2<minn))
            {
                minn=k1-k2;
                ans=i;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Lngxling/article/details/82904898