码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 4621: Tc605

时间:2017-10-23 15:03:41      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:desc   algo   题解   include   转移   amp   struct   cstring   lower   

 

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

标签:desc   algo   题解   include   转移   amp   struct   cstring   lower   

原文地址:http://www.cnblogs.com/renjianshige/p/7716686.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!