题意简述
有一个序列,不确定,给定其长度
n
(
<
=
1
e
4
)
n(<=1e4)
n(<=1e4),以及其中最大的数。这个最大的数在点
k
(
1
<
=
k
<
=
n
)
k(1<=k<=n)
k(1<=k<=n),高为
h
(
<
=
1
e
6
)
h(<=1e6)
h(<=1e6),以及
r
r
r个关系。每个关系是这样表示的:
两个
(
a
,
b
)
(a,b)
(a,b):第
a
a
a个
<
=
<=
<=第
b
b
b个,并且
[
a
+
1
,
b
−
1
]
[a+1,b-1]
[a+1,b−1]中都严格比
a
a
a小(没有等于的)。
(注意是
<
=
<=
<=,洛谷上面有误,看英文珂知)
请最大化序列中的每个数,输出这个最大的序列。
思路
我们想想,如果没有限制,肯定就每个都 h h h了。但是为什么不行呢?因为有限制。
那么,一对限制
(
a
,
b
)
(a,b)
(a,b)出来之后,最优策略是什么呢?很明显,就是把
[
a
+
1
,
b
−
1
]
[a+1,b-1]
[a+1,b−1]中的数都
−
1
-1
−1。
那么两个呢?三个呢?四个呢?。。。。
经过更深入的思考,我们发现,我们只要重叠那个区间减一的操作即珂。就是这个序列一开始都是
h
h
h,然后对于一个
(
a
,
b
)
(a,b)
(a,b),我们在
(
a
+
1
,
b
−
1
)
(a+1,b-1)
(a+1,b−1)内减一,然后输出序列即珂。
那么我们如何维护呢?线段树和树状数组自然是珂以做的,但是有更简单的方法。对于这个题来说,差分是个好办法。然后最后求前缀和,加上
h
h
h,即珂。
(有一个细节注意,就是这个题里面相同的
(
a
,
b
)
(a,b)
(a,b)会出现很多次,要用一个
m
a
p
map
map判重。所以这就活活给时间复杂度多了一个
l
o
g
log
log。)
代码:
#include<bits/stdc++.h>
using namespace std;
namespace Flandle_Scarlet
{
#define N 200100
map<pair<int,int>,bool> vis;
int n,id,h,r;
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Input()
{
R1(n),R1(id),R1(h),R1(r);
}
int d[N];
void Soviet()
{
for(int i=1;i<=r;++i)
{
int a,b;R1(a),R1(b);
if (a>b) swap(a,b);
if (vis[make_pair(a,b)]) continue;
d[a+1]--;
d[b]++;//[a+1,b-1]内减一
vis[make_pair(a,b)]=1;
}
for(int i=1;i<=n;++i)
{
d[i]+=d[i-1];//原地变前缀和
printf("%d\n",d[i]+h);//加上h
}
}
void IsMyWife()
{
if (0)
{
freopen("","r",stdin);
freopen("","w",stdout);
}
Input();
Soviet();
}
};
int main()
{
Flandle_Scarlet::IsMyWife();
return 0;
}