zoukankan      html  css  js  c++  java
  • CF1434E. A Convex Game

    题目描述

    题解

    虽然不会做,但是感觉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
    ":"NO
    ");
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Windows的VNC客户端连接Linux无法复制粘贴
    iText中输出中文
    POI写docx文件table中的单元格水平、垂直对齐
    OpenOffice将MS docx转换成pdf文件偶数页眉不显示问题解决办法
    Servlet下载文件迅雷不支持问题真相之一
    Java处理JSON的工具类(List、Map和JSON之间的转换)——依赖jsonlib支持Map嵌套
    EasyUI的combobox组件Chrome浏览器不兼容问题解决办法
    Tomcat5内存简单优化
    jQuery使用动态渲染表单功能完成ajax文件下载
    POI导出Word插入复选框
  • 原文地址:https://www.cnblogs.com/gmh77/p/13898643.html
Copyright © 2011-2022 走看看