• 7397. 【2021.11.18 NOIP提高组联考】C. I love random


    Description

    给定一个 \(1 \sim n\) 的排列数组 \([P[1], P[2], \ldots, \ldots, P[n]]\)
    现在给定一段代码,你可以对这个数组 \(P\) 进行任意次操作(可以不操作):

    void modify(int P[], int n){
    	int l=rand()%n+1,r=rand()%n+1;
     	if (l>r) swap(l,r);
    	int minp=n;
    	for(int i=1;i<=r;++i)
    		minp=min(minp,P[i]);
    	for(int i=1;i<=r;++i)
    		P[i]=minp;
    } 
    

    问最后能形成多少种不同的 \(P\) 数组,并对答案取模 \(10^{9}+7\)
    例如, \(n=3, P=[1,3,2]\)
    (1)不操作,得到 \([1,3,2]\)
    (2)操作 \([1,2]\),得到 \([1,1,2]\)
    (3)操作 \([1,3]\),得到 \([1,1,1]\)
    (4)操作 \([2,3]\),得到 \([1,2,2]\)
    可以证明至多只能形成这四种数组 \(P\)

    \(n\le 5\times 10^3\)

    Solution

    题目过于花里胡哨,简单来说,就是给出一个 \(1\sim n\) 的序列,每次操作可以使得区间 \([l,r]\) 里每一个数变成区间的最小值,问不同的序列个数。

    首先对于一个 \(P_i\),我们可以预处理出他所能影响到的左右端点,记为 \(L_i\)\(R_i\)

    那么我们可以认为,\(P_i\) 可以使得区间 \([L_i,R_i]\) 中任意一个子区间的值变为 \(P_i\),也可以是空区间,但只能是一个。

    具体操作是可以先用 \(P_i\) 覆盖,然后再用比 \(P_i\) 小的 \(P_j\) 来覆盖不应该覆盖的地方。

    考虑 \(dp\),设 \(f_i\) 表示到了第 \(i\) 个区间 \([L_i,R_i]\) 的序列数。

    转移 \(f_j=\sum_{k=L_i-1}^{j}f_k(L_i\le j\le R_i)\)

    时间复杂度 \(\mathcal O(n^3)\),无法通过此题。

    考虑优化,可以采取前缀和优化,转移式变为 \(f_j+=f_{j-1}(L_i\le j\le R_i)\)

    此时时间复杂度 \(\mathcal O(n^2)\),空间复杂度 \(O(n)\)

    Code

    #include<cstdio>
    #define N 5005
    #define mod 1000000007
    using namespace std;
    int n,a[N],l[N],r[N],f[N];
    int main()
    {
    	freopen("C.in","r",stdin);
    	freopen("C.out","w",stdout);
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i)
    		scanf("%d",&a[i]);
    	for (int i=1;i<=n;++i)
    	{
    		l[i]=r[i]=i;
    		while (a[i]<a[l[i]-1]) --l[i];
    		while (a[i]<a[r[i]+1]) ++r[i];
    	}
    	f[0]=1;
    	for (int i=1;i<=n;++i)
    		for (int j=l[i];j<=r[i];++j)
    			f[j]=(f[j]+f[j-1])%mod;
    	printf("%d\n",f[n]);
    	return 0;
    } 
    
  • 相关阅读:
    【资料整理】面向对象
    【资料整理】函数(方法)
    【资料整理】数组
    【资料整理】循环、判断、三元表达式
    【资料整理】类型转换、运算符
    【资料整理】c#基础
    线性表的链式表示和实现
    线性表
    PAT 乙级1062最简分数
    HDU 1027(全排列)
  • 原文地址:https://www.cnblogs.com/Livingston/p/15574657.html
Copyright © 2020-2023  润新知