zoukankan      html  css  js  c++  java
  • CF1450D Solution

    题目链接

    题解

    将题意简化,对于(i)满足(1le ile n),设(b_j=a_j)(a_{j+i-1})的最小值((1le jle n-i+1)),我们需要判断(b)序列是否为(n-i+1)的全排列。因为枚举每一个(j)的时间已经是(O(n^2)),而此题时间复杂度需要在(O(nlogn))以内,所以只能考虑转移(i),可以依据以下三个规律进行递推:

    1. 如果(n-i+1)(a)序列中不存在,则所有(le i)的长度都无法实现全排列(如输入样例(3,3,2))。

    2. 如果(n-i+1)(a)序列中出现超过(1)次,则在所有(<i)的长度中(n-i+1)一定会作为最小值出现超过一次,也无法实现全排列(如输入样例(1,3,2,1))。

    3. (n-i+1)在所有(ge n-i+1)的值中只能处于开始或最后,若非如此在所有(<i)的长度中也会出现多次(如输入样例(1,5,3,4,2)中的({5,3})({3,4}))。

    (a)数组中从后向前枚举(i)即可。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5+10;
    int a[N],sum[N];//sum[i]:i在a数组中出现的次数 
    bool ans[N];
    int main()
    {
    	int t,n;
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++) sum[i]=ans[i]=0;
    		for(int i=1;i<=n;i++) {scanf("%d",&a[i]); sum[a[i]]++;}
    		int l=1,r=n; ans[1]=1;//l/r:a数组中大于等于i的值的最左/右端
    		for(int i=n;i>=1;i--)
    		{
    			int b=n-i+1;
    			if(!sum[b]) break;//规律1
    			ans[i]=1;
    			if(sum[b]>1) break;//规律2
    			if(a[l]!=b && a[r]!=b) break;//规律3
    			if(a[l]==b)//维护l、r
    				while(a[++l]<b);
    			if(a[r]==b)
    				while(a[--r]<b);
    		}
    		for(int i=1;i<=n;i++)
    			if(sum[i]!=1) {ans[1]=0; break;}
    		for(int i=1;i<=n;i++) printf("%d",ans[i]);
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    2015 多校联赛 ——HDU5389(dp)
    spring MVC配置详解
    面试题整理11
    面试题整理09
    Spring和SpringMVC的区别
    SpringMVC01
    js中typeof与instanceof用法小记
    Java 可变参数
    log4j文件的配置
    Hibernate 分组查询 子查询 原生SQL
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14220564.html
Copyright © 2011-2022 走看看