zoukankan      html  css  js  c++  java
  • [CF314C](Sereja and Subsequences)

    • 题意

    给你一个序列

    把这个序列的每一个不下降子序列拿出来

    对于每一个子序列,一个可行序列为:

    1.由正整数组成,长度和原子串相同

    2.不大于原子串

    求所有,所有的可行串

    • solution

    dp

    (dp_i)为以i为结尾的所有可行串的总数

    对于最简单的严格单调递增序列有(即样例2)

    (dp_i)=( (sum^{i-1}_{r=1}) (dp_r))*(dp_i)+(dp_i)

    但是重复怎么办?

    我们减去上一个重复点的dp值(推荐手模一下以便理解)

    举个例子

    3

    1 2 2

    这个序列,(dp_1)=1,(dp_2)=(1)$ imes (2+2=4,)dp_3(=(1+4)) imes(2+2-)dp_2$=8

    但是序列递减部分怎么办,不加就可以了嘛qwq

    但是时间复杂度(n^2)怎么办(syk:还不简单),用树状数组维护一下就降下来辣

    如上

    • code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define int long long
    #define lowbit(x) (x&-x)
    using namespace std;
    const int mod=1000000007;
    int tree[2000005*4];
    int dp[2000005];
    int from[2000005];//from 即上一个重复点的dp值
    int a[200005];
    int n,poss=1,ans=0;
    void add(int x,int k) {for(x;x<=2000000;x+=lowbit(x))tree[x]+=k,tree[x]%=mod;}
    int sum(int k) {
        int anss=0;
        for(k;k;k-=lowbit(k))anss+=tree[k],anss=(anss%mod+mod)%mod;
        return anss;
        }
    signed main(){
      scanf("%lld",&n);
      memset(from,-1,sizeof(from));
      for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
      for(int i=1;i<=n;i++){
         dp[i]=(sum(a[i])*a[i]%mod+a[i])%mod;//sum(a[i])这样就可以保证加的都是小于等于a[i]的
         if(from[a[i]]!=-1)dp[i]-=from[a[i]];
         dp[i]=(dp[i]%mod+mod)%mod;
         ans+=dp[i];
         ans=(ans%mod+mod)%mod;
         from[a[i]]=(sum(a[i])*a[i]+a[i])%mod;
         add(a[i],dp[i]);//注意传的是a[i]而不是i
         } 
      cout<<ans%mod;
      }
    
  • 相关阅读:
    linux安装glibc2.14
    Redhat下如何查看nvidia显卡的工作状况
    Tensorflow下指定显卡占用比例参数配置
    Linux系统终端session保持服务工具-Tmux
    error while loading shared libraries: libevent-2.1.so.6 的解决办法
    机器学习环境配置系列六之jupyter notebook远程访问
    机器学习环境配置系列五之keras2
    机器学习环境配置系列四之theano
    LeetCode 27
    LeetCode 26
  • 原文地址:https://www.cnblogs.com/stepsys/p/10387978.html
Copyright © 2011-2022 走看看