BZOJ 4621: Tc605

Posted 人间失格

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4621: Tc605相关的知识,希望对你有一定的参考价值。

 

Description

最初你有一个长度为 N 的数字序列 A。为了方便起见,序列 A 是一个排列。
你可以操作最多 K 次。每一次操作你可以先选定一个 A 的一个子串,然后将这个子串的数字全部变成原来这个子串的最大值。问最终有几种可能的数字序列。答案对 1e9+7 取模。
 

 

Input

第一行两个数 N 和 K。第二行 N 个数,描述一个排列 A。 
N,K<=500,
有6组数据N>100,有梯度
 

 

Output

输出一个数,表示答案在模域下的值。 
 

 

Sample Input

3 2
3 1 2

Sample Output

4

 

题解:

  我太水了,连普及组的题目都看了题解。
  这个题目,我们考虑对于每个点,算出他向左,向右最多可以延伸多少,然后我们就可以把他看成一个区间,然后我们有m次机会使得这个区间出现,如果什么都没有发生改变,也就没有用这次的机会,所以我们可以得到一个状态,dp[i][j]表示已经覆盖到了i,用了j次机会的方案数。然后转移就比较简单了。
 
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#define mod 19260817
#define MAXN 300100
#define ll long long
using namespace std;
struct tree{
    int l,r;ll sum;
}a[MAXN*4];
int v[MAXN],b[MAXN];
ll num1[MAXN],num2[MAXN];int n;
 
void pushup(int xv){
    a[xv].sum=(a[xv*2].sum+a[xv*2+1].sum)%mod;
}
 
void build(int xv,int l,int r){
    if(l==r){
        a[xv].l=a[xv].r=r;
        a[xv].sum=0;return;
    }
    a[xv].l=l,a[xv].r=r;
    int mid=(l+r)/2;
    build(xv*2,l,mid),build(xv*2+1,mid+1,r);
    pushup(xv);
}
 
ll query(int xv,int l,int r){
    int L=a[xv].l,R=a[xv].r,mid=(L+R)/2;
    if(l==L&&R==r){
        return a[xv].sum;
    }
    if(r<=mid) return query(xv*2,l,r);
    else if(l>mid) return query(xv*2+1,l,r);
    else return (query(xv*2,l,mid)+query(xv*2+1,mid+1,r))%mod;
}
 
void insert(int xv,int ps,int x){
    int l=a[xv].l,r=a[xv].r,mid=(l+r)/2;
    if(l==r){
        a[xv].sum=(a[xv].sum+x)%mod;
        return;
    }
    if(ps<=mid) insert(xv*2,ps,x);
    else insert(xv*2+1,ps,x);
    pushup(xv);
}
 
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&v[i]),b[i]=v[i];
    sort(b+1,b+n+1);
    int k=unique(b+1,b+n+1)-b-1;
    build(1,1,k);
    for(int i=1;i<=n;i++){
        v[i]=lower_bound(b+1,b+k+1,v[i])-b;
    }
    for(int i=1;i<=n;i++){
        if(v[i]-1>0) num1[i]=query(1,1,v[i]-1);
        insert(1,v[i],b[v[i]]);
    }
    build(1,1,k);
    for(int i=n;i>=1;i--){
        if(v[i]+1<=k) num2[i]=query(1,v[i]+1,k);
        insert(1,v[i],b[v[i]]);
    }
    ll ans=0;
    for(int i=1;i<=n;i++){
        ll hh=num1[i]*b[v[i]];hh%=mod;
        hh=(hh*num2[i])%mod;
        ans=(ans+hh)%mod;
    }
    printf("%lld",ans);
    return 0;
}

 

以上是关于BZOJ 4621: Tc605的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 4621: Tc605 动态规划

bzoj4621: Tc605

BZOJ 4621: Tc605

Tc605

bzoj1195 最短母串

谷歌地图的“错误膨胀类片段”