CF1434E. A Convex Game
阿新 • • 發佈:2020-10-29
題目描述
題解
雖然不會做,但是感覺3500還是高了
首先在博弈問題中,如果一個狀態的sg=i,那麼一定存在一條從該狀態出發的長度為i的鏈
設f[i,j]表示以i結尾,最後差為j的sg,則顯然sg不超過√2maxc
所以直接dp存sg,設f[i,j]表示以i結尾,sg為j的最大差,顯然隨著差的不斷減少sg單調不減
列舉後面的k來從f[k,j]->f[i,j+1],如果恰好在能轉移的區間(a[k]-a[i]∈[f[k,j+1]+1,f[k,j]])內則用a[k]-a[i]-1來更新
畫一下式子發現f[i,j]更新的是一段區間,通過預處理g[i]=j表示<=i的最大a[j]來得出更新範圍,直接更新後用並查集刪除(合併)即可,一個狀態只會被更新一次
由於求的是sg,所以還要對f[i]取字首min
時間複雜度O(n*maxc+Σm*√maxc*α)
code
#include <bits/stdc++.h> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define inf 2000000000 #define ll long long //#define file using namespace std; int a[100001],f[100001][451],fa[451][100001],g[100001],T,n,i,j,k,l,ans,mx,L,R; int gf(int T,int t) { if (fa[T][t]==t) return t; fa[T][t]=gf(T,fa[T][t]); return fa[T][t]; } void Change(int T,int t,int s) {f[t][T]=(f[t][T]<-inf)?s-a[t]:f[t][T];} void link(int T,int x,int y) { if (!x || !y) return; if (gf(T,x)!=gf(T,y)) fa[T][fa[T][x]]=fa[T][y]; } void change(int T,int x,int y,int s) { int i; while (x<=y) { y=gf(T,y); if (y<x) break; Change(T,y,s); link(T,y,y-1),--y; } } int main() { #ifdef file freopen("CF1434E.in","r",stdin); #endif scanf("%d",&T); for (;T;--T) { scanf("%d",&n); memset(g,0,sizeof(g)),mx=0; memset(f,128,(n+1)*sizeof(f[0])); fo(i,1,n) scanf("%d",&a[i]),mx=max(mx,a[i]),g[a[i]]=i; fo(i,1,mx) g[i]=(!g[i])?g[i-1]:g[i]; fo(i,1,n) fo(j,0,450) fa[j][i]=i; f[n][0]=inf; fd(i,n,2) { f[i][0]=inf,j=0; while (f[i][j+1]>-inf) f[i][j+1]=min(f[i][j+1],f[i][j]),++j; j=0; while (f[i][j]>-inf) { while (f[i][j]==f[i][j+1]) ++j; L=max(a[i]-f[i][j],1),R=(f[i][j+1]>-inf)?a[i]-f[i][j+1]-1:mx,R=max(R,0); L=g[L-1]+1,R=min(g[R],i-1); change(j+1,L,R,a[i]-1); ++j; } } f[1][0]=inf,l=0; fo(i,1,n) { j=0; while (f[i][j+1]>-inf) ++j; l=max(l,j); } ans^=l+1; } printf(ans>0?"YES\n":"NO\n"); fclose(stdin); fclose(stdout); return 0; }