题面

传送门

题解

我的做法似乎非常复杂啊……

首先最长上升子序列长度就等于把它反过来再接到前面求一遍,比方说把\(2134\)变成\(43122134\),实际上变化之后的求一个最长上升子序列和方案数就是答案了

最长上升子序列随便求求,主要是这个方案数很麻烦啊……我的做法是对每一个长度开一个动态开点线段树,然后每次在对应的长度里二分跑前缀和

其实这里完全不用动态开点线段树的,直接把权值离散一下然后一棵线段树就够了,跑得飞快

其实这里连线段树都不需要直接树状数组就可以维护前缀最大值和方案之和了

然后没有然后了

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(int i=(a),I=(b)-1;i>I;--i)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=4e5+5,P=1e9+7,M=(N<<5)+5;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
int sum[M],lc[M],rc[M],rt[N],tot;
int a[N],f[N],g[N],b[N],m,n,res,mx,lim;
void query(int p,int l,int r,int x){
if(!p||l==r)return res=add(res,sum[p]),void();
int mid=(l+r)>>1;
if(x<=mid)query(lc[p],l,mid,x);
else res=add(res,sum[lc[p]]),query(rc[p],mid+1,r,x);
}
void ins(int &p,int l,int r,int x,int val){
if(!p)p=++tot;sum[p]=add(sum[p],val);
if(l==r)return;
int mid=(l+r)>>1;
x<=mid?ins(lc[p],l,mid,x,val):ins(rc[p],mid+1,r,x,val);
}
int main(){
// freopen("testdata.in","r",stdin);
n=read();
fp(i,1,n)a[i]=b[i]=read();
sort(b+1,b+1+n),lim=unique(b+1,b+1+n)-b-1;
fp(i,1,n)a[i]=lower_bound(b+1,b+1+lim,a[i])-b;
reverse(a+1,a+1+n);
fp(i,1,n)a[(n<<1)-i+1]=a[i];
n=(n<<1),m=0,b[0]=0;
fp(i,1,n){
if(a[i]>b[m])f[i]=++m,b[m]=a[i];
else{
int k=lower_bound(b+1,b+1+m,a[i])-b;
f[i]=k,b[k]=a[i];
}
if(f[i]==1)g[i]=1;
else res=0,query(rt[f[i]-1],1,lim,a[i]-1),g[i]=res;
if(i>(n>>1)&&f[i]==f[n-i+1])g[i]=dec(g[i],g[n-i+1]);
ins(rt[f[i]],1,lim,a[i],g[i]);
cmax(mx,f[i]);
}
res=0;
fp(i,(n>>1)+1,n)if(f[i]==mx){
res=add(res,g[i]);
if(f[n-i+1]==mx)res=add(res,g[n-i+1]);
}
res=mul(res,ksm(2,(n>>1)-mx));
printf("%d %d\n",mx,res);
return 0;
}

最新文章

  1. 【C#公共帮助类】 Utils 10年代码,最全的系统帮助类
  2. 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现
  3. linux文件描述符open file descriptors与open files的区别
  4. 关于NSDate和NSDateFormatter的几个常用方法
  5. IP HELPER GetAdaptersAddresses 函数
  6. 年度十佳 DevOps 博客文章(后篇)
  7. 从一个SVN下载的导入另一个SVN里面
  8. usbmanger android 底下USB的工作模式
  9. Android EventBus 3.0 实例使用详解
  10. perl 正则表达式之匹配
  11. Android实现无线调试自己的应用
  12. Python中的垃圾回收与del语句
  13. Mongodb 的ORM框架 Morphia之注解
  14. PXE 自动安装物理机 (DHCP服务由路由提供, 不能再配置)
  15. tkinter python(图形开发界面)
  16. 通过COM组件方式实现java调用C#写的DLL文件 转
  17. selinux 设置的彻底理解 并要 熟练经常的使用
  18. 各版本.NET委托的写法回顾(转)
  19. Android-Recyclerview的简单使用
  20. 菜鸟学Java(十七)——Jboss瘦身

热门文章

  1. 【转】跨DLLnew delete问题
  2. 分享 - 普通程序员如何转向AI方向
  3. 【318】C# 学习笔记
  4. lombok 注解使用
  5. Spring Cloud Config配置中心的使用
  6. 网页中给超链接添加&quot;是否确认&quot;的方法
  7. lib
  8. Golang之实现一个负载均衡算法(随机,轮询)
  9. Python爬虫利器一之Requests库的用法
  10. 关于Safari浏览器使用的几点总结