1. 程式人生 > >【FCS NOI2018】福建省冬摸魚筆記 day4

【FCS NOI2018】福建省冬摸魚筆記 day4

cpp day force 價值 不知道 light 斜率 單調性 甚至有

第四天。

動態規劃專題,講師:閆神

講了一些DP優化技巧,然而思想難度好大啊……根本沒想到能優化那地步,連DP方程都沒有呢。

不過有幾題我還是想明白了。

講了單調隊列,決策單調性,四邊形不等式,斜率優化,甚至有DP套DP,然而就是雙重DP,什麽背包+數位罷了。

輪廓線DP,插頭DP都有點難寫啊……不過也是狀壓DP的一大內容 。還有概率DP,期望DP,非常恐怖。


中午劃水。


下午的題比較良心。T1不知道寫了什麽寫掛了,T2就很好AC,T3毒瘤題。

【T1】

題面:m個青蛙,它們可以跳無限遠,但是第i只青蛙每一次跳比d長時,要花費ci。

河面上,有n+2個石頭,起點終點2個,中間n個。中間的石頭只能被跳到1次,並且一定要被跳到1次。

問所有青蛙過河最小花費。

題解:二分多少只青蛙可以不花費任何代價過河,那麽其他的青蛙就直接飛過河,代價就是最小的那麽多個代價的和。

如何check?顯然每次我們讓最左邊的青蛙跳到右邊第一個沒有跳過的石頭上,如果有代價就掛了,一直到終點都沒有代價就好了。

特判一只都不行的情況,顯然所有青蛙都飛過去,除了最小代價的,那只青蛙一個一個跳。

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k,d,maxz;
int a[100005];
long long c[100005];
bool check(int x){
	for(int i=0;i<=k-x+1;++i)
		if(a[i+x]-a[i]>d) return 0;
	return 1;
}
int main(){
	freopen("frog.in","r",stdin);
	freopen("frog.out","w",stdout);
	int T; scanf("%d",&T);
	while(T--){
		scanf("%d%d%d%d",&n,&m,&k,&d); maxz=0;
		for(int i=1;i<=m;++i) scanf("%lld",c+i);
		for(int i=1;i<=k;++i) scanf("%d",a+i);
		if(d>=n-1) {puts("0"); continue;}
		sort(c+1,c+m+1); sort(a+1,a+k+1); a[0]=1; a[k+1]=n;
		for(int i=1;i<=m;++i) c[i]+=c[i-1];
		int l=0,r=min(m,k),mid,ans=-1;
		while(mid=l+r>>1,l<=r)
			check(mid)?l=mid+1,ans=mid:r=mid-1;
		if(ans==0){
			long long sum=c[m]-c[1];
			for(int i=1;i<=k+1;++i) if(a[i]-a[i-1]>d) sum+=c[1];
			printf("%lld\n",sum);
		}
		else printf("%lld\n",c[m-ans]);
	}
	return 0;
}

【T2】

題面:定義一個字符串的價值為:長度^2/最短循環節長度。給定一個只有a,b,c的字符串,求出它子序列中價值的最大值。

題解:重定義價值=長度*循環節最大循環次數。那麽對於長度為4的任意串,根據抽屜原理,必有一個字符出現2次,那麽價值為2*2=原來的價值4,也就是說,長度為4的任意串不會更優。

以此類推,我們知道長度為7或更長的都不會更優,長度為5和6的只有一些(相比其中更短的)會更優。

總計不超過102種,於是每一種都check一下,就得到答案。

我的代碼循環展開了,太TM長了,327行,就不貼了。

【FCS NOI2018】福建省冬摸魚筆記 day4