最初你有一个长度为 N 的数字序列 A。为了方便起见,序列 A 是一个排列。
你可以操作最多 K 次。每一次操作你可以先选定一个 A 的一个子串,然后将这个子串的数字全部变成原来这个子串的最大值。问最终有几种可能的数字序列。答案对 1e9+7 取模。
标签:desc algo 题解 include 转移 amp struct cstring lower
#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; }
标签:desc algo 题解 include 转移 amp struct cstring lower
原文地址:http://www.cnblogs.com/renjianshige/p/7716686.html