把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

BZOJ #2489. Random Sequence

题面传送门
非常奇妙的dp。
首先我们发现这个东西相当于是最大子段和和最小子段和的绝对值取max。
考虑最大子段和的一种求法:维护前缀的前缀最小值,然后用当前的前缀与其相减得到答案。
而最小子段和也有一种求法:维护前缀的后缀最小值,然后用当前的前缀与其相减得到答案。
因此这个东西的值相当于最大前缀和减去最小前缀和。这样就好做很多。
我们考虑dp:设\(dp_{i,j,mx,mi}\)为dp到了第\(i\)个数,当前前缀和为\(j\),最大前缀和为\(mx\),最小前缀和为\(mi\)。这样是\(O(n^4)\)的,通过非常困难。
我们发现我们只需要知道\(mx-j\)\(j-mi\),所以改变状态为\(dp_{i,a,b}\)\(a=Mx-j,b=j-Mi\)的答案。然后特判\(a=0\)是的\(+1\)\(b=0\)\(-1\)。这样是\(O(n^3)\)的,如果你是wys可以考虑一下
我们考虑\(b\)\(a\)的影响,如果是\(-1\)无论\(b\)是否为\(0\)\(a\)\(+1\)\(a\)\(b\)也一样,最后的贡献是\(a+b\),因此我们可以将\(a\)\(b\)分开来\(dp\),然后就可以做到\(O(n^2)\),轻松卡过。
非常奇妙的是printf%.6lf四舍五入在.5的时候是随机取舍的,因此要扰动一下才能正确输出。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (1500+5)
#define M (30000+5)
#define K (6)
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n=1500,T,m,La,Ne;db F[2][N],Ts[N];
int main(){
	freopen("1.in","r",stdin);
	int i,j,h;F[0][0]=1;Ne=0;La=1;for(i=1;i<=n;i++){Ne^=1;La^=1;
		for(j=0;j<i;j++) (j?F[Ne][j-1]:F[Ne][j])+=0.5*F[La][j],F[Ne][j+1]+=F[La][j]*0.5,F[La][j]=0;
		for(j=0;j<=i;j++)Ts[i]+=F[Ne][j]*j*2;
	}scanf("%d",&T);for(i=1;i<=T;i++) scanf("%d",&m),printf("Case %d: %.6lf\n",i,(Ts[m])+1e-15);
}
posted @ 2022-06-27 21:44  275307894a  阅读(32)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end