P5026 Lycanthropy(差分)

洛谷链接:https://www.luogu.com.cn/problem/P5026

P5026 Lycanthropy

题目背景

小正方形亲眼看见了自己昔日的朋友被卷进了黑暗的深渊,然而它无力阻止……

现在它的朋友已经向它发起了攻击,因此小正方形不得不抵抗。

题目描述

我们把山顶上的湖泊看作一条长度为 \(m\) 的直线,一开始水深都在水平线上,我们视作此时的水深为 '0'

接下来,在一瞬间,小正方形的"朋友"们跳起并扎入水中,导致在入水点的水降低而远离入水点的水升高,注意两个 "朋友" 可能在同一地点入水。

小正方形的每个朋友有一个体积数值 \(v\),当体积为 \(v\) 的一个朋友跳入水中,我们设入水点为 \(i\),将会导致 \(i - v + 1\)\(i\) 的水位依次降低 \(1,2,\cdots,v\)

同样地,第 \(i\)\(i + v - 1\) 的水位会依次降低 \(v,v - 1,\cdots,1\).

相对应地,\(i - v\) 的水位不变, \(i - v - 1\)\(i - 2 * v\) 水位依次增加 \(1,2,\cdots,v\)\(i - 2 * v\)\(i - 3 * v + 1\) 水位依次增加 \(v,v - 1,\cdots,1\)

同样,\(i + v\) 水位不变,\(i + v + 1\)\(i + 2 * v\) 水位增加 \(1,2,\cdots,v\)\(i + 2 * v\)\(i + 3 * v - 1\) 水位依次增加 \(v,v - 1,\cdots,1\)

现在小正方形想要穿过这个湖,他想要知道在这 \(n\) 个"朋友"跳入水中后湖上每个节点的水位,你能帮帮它吗?

输入格式

第一行为两个整数 \(n\),\(m\),表示"朋友"的数目与湖泊的宽度。

接下来 \(n\) 行,一行两个整数 \(v,x\),表示第 \(i + 1\) 个朋友的体积与入水点。

输出格式

一行 \(m\) 个整数,第 \(i\) 个整数表示 \(i\) 号位的水深。

输入输出样例 #1

输入 #1

1 10
1 5

输出 #1

0 0 1 0 -1 0 1 0 0 0

输入输出样例 #2

输入 #2

2 10
2 6
3 1

输出 #2

-2 0 0 0 0 0 2 2 2 2

说明/提示

对于 \(30\%\) 的数据,\(n <= 50,m <= 500\)

对于 \(70\%\) 的数据,\(n <= 10^5,m <= 10^5\)

对于 \(100\%\) 的数据,\(n <= 10^6,m <= 10^6,1 <= v <= 10000,1 <= x <= m\)

思路:

这道题的难度在于处理好边界条件,我们可以通过将起始位置平移到一个较大数字,保证下标不会越界到负数去,我们可以通过观察数组的数据量来定S,具体看题解,其实将题目提到的变化转换成四个等差差分数组来实现。

题解:

#include <bits/stdc++.h>
using namespace std;
const int N=5e6+10;
const int S = 3e6;
typedef long long ll;
int n,m;
int t=1;
int v,x;
int arr[N];


void st(int l,int r,int s,int e,int d)
{
    arr[l+S]+=s;
    arr[l+S+1]+=d-s;
    arr[r+S+1]-=d+e;
    arr[r+S+2]+=e;
}


int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    // cin>>t;
    cin>>n>>m;
    while(n--)
    {
        cin>>v>>x;
        // x-3v - x-2v
        st(x-3*v+1,x-2*v,1,v,1);
        // x-2v - x
        st(x-2*v+1,x,v-1,-v,-1);
        // x - x+2v
        st(x+1,x+2*v,-v+1,v,1);
        // x - x+3v
        st(x+2*v+1,x+3*v-1,v-1,1,-1);
    }
    ll sum=0;
    for(int i=1;i<=m+S;i++)
    {   
        arr[i]+=arr[i-1];
        
    }
    for(int i=1;i<=m+S;i++)
    {   
        arr[i]+=arr[i-1];
        
    }
    for(int i=1;i<=m;i++)cout<<arr[i+S]<<' ';
    cout<<endl;

    return 0;
}
posted @ 2025-06-19 13:20  屈臣  阅读(23)  评论(0)    收藏  举报