1. 程式人生 > 實用技巧 >LOJ #6370. 「VK Cup 2018 Round 2」河畔獵奇者

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

昨天的模擬賽中唯一一道之前沒做過的題,然後看到陳指導10min寫了個線段樹維護等差數列我嚇得不敢說話,然後想了一下發現就是個SB題

首先我們考慮讓\(d_i\)最小時,水位線的總數應該儘量小,因此如果允許的話我們希望在劃線的時候除非只能劃在最下面,否則都可以和原來的標記劃重合

然後我們根據樣例就可以看出,這樣雖然保證了最小,但是因為之前省下來的線導致當前位置就算把線劃在最下面也不夠用了,就需要調整之前劃的重合的線

由於修改時肯定只能在原來的位置之上劃線,因此後面的\(d_i\)都會被影響

換句話說假設當前位置\(i\)不合法,在之前\(j\)位置劃過重合的線,那麼顯然\(d_k,k\in[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;
}