LOJ #6370. 「VK Cup 2018 Round 2」河畔猎奇者

昨天的模拟赛中唯一一道之前没做过的题,然后看到陈指导10min写了个线段树维护等差数列我吓得不敢说话,然后想了一下发现就是个SB题

首先我们考虑让(d_i)最小时,水位线的总数应该尽量小,因此如果允许的话我们希望在划线的时候除非只能划在最下面,否则都可以和原来的标记划重合

然后我们根据样例就可以看出,这样虽然保证了最小,但是因为之前省下来的线导致当前位置就算把线划在最下面也不够用了,就需要调整之前划的重合的线

由于修改时肯定只能在原来的位置之上划线,因此后面的(d_i)都会被影响

换句话说假设当前位置(i)不合法,在之前(j)位置划过重合的线,那么显然(d_k,kin[j,i-1])都要加一

那么我们发现每次对当前不合法位置操作时,找到之前的最右边的重合位置即可,用一个轻松维护

复杂度(O(n))

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,x,stk[N],top,c; long long ans;
int main()
{
	RI i; for (scanf("%d",&n),i=1;i<=n;++i)
	{
		scanf("%d",&x); while (c<x) ans+=i-stk[top--],++c;
		if (c==x) ++c; else stk[++top]=i; ans+=c-x-1;
	}
	return printf("%lld",ans),0;
}
原文地址:https://www.cnblogs.com/cjjsb/p/13354120.html