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;
}

浙公网安备 33010602011771号