降雷皇 解题报告
降雷皇
问题描述
降雷皇哈蒙很喜欢雷电, 他想找到神奇的电光。
哈蒙有 \(n\) 条导线排成一排, 每条导线有一个电阻值, 神奇的电光只能从一根导线传到电阻比它大的上面, 而且必须从左边向右传导,当然导线不必是连续的。
哈蒙想知道电光最多能通过多少条导线, 还想知道这样的方案有多少。
输入格式
第一行两个整数 $n $ 和 $type $。 $type $ 表示数据类型
第二行 $n $ 个整数表示电阻。
输出格式
第一行一个整数表示电光最多能通过多少条导线。
如果 $type=1 $ 则需要输出第二行, 表示方案数, 对 $123456789 $ 取模。
数据范围与约定
对于 $20% $ 的数据 $n\le 10 $;
对于 $40% $ 的数据 $n\le 1000 $;
对于另外 $20% $ 的数据 $type=0 $;
对于另外 $ 20% $ 的数据保证最多能通过不超过 $100 $ 条导线;
对于 $100% $ 的数据 $n\le 100000 $,电阻值不超过 $100000 $。
简单的 \(\tt{LIS}\)求方案的煞笔题,又挂了...写篇博客记录一下。
我是直接把方案和最大值放一个结构体里了,线段树的节点值域代表电阻值。
然后我以为电阻值小于 $n $,挂分点 $1 $
因为每次查询的是 $r-1 $,所以线段树上要搞 \(0\)节点,挂分点 $2 $
Code:
#include <cstdio>
const int N=1e5;
const int mod=123456789;
int n,typ;
struct node
{
int mx,cnt;
node(){mx=cnt=0;}
node friend operator +(node n1,node n2)
{
node n3;
if(n1.mx==n2.mx)
{
n3.mx=n1.mx,n3.cnt=(n1.cnt+n2.cnt)%mod;
if(n3.mx==0) n3.cnt=1;
return n3;
}
return n1.mx>n2.mx?n1:n2;
}
}mx[(N+10)<<2],dp[N+10],ans;
#define ls id<<1
#define rs id<<1|1
void build(int id,int l,int r)
{
mx[id].cnt=1;
if(l==r) return;
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
}
void change(int id,int l,int r,int p,node d)
{
if(l==r)
{
mx[id]=mx[id]+d;
return;
}
int mid=l+r>>1;
if(p<=mid) change(ls,l,mid,p,d);
else change(rs,mid+1,r,p,d);
mx[id]=mx[ls]+mx[rs];
}
node query(int id,int l,int r,int p)
{
if(l==r) return mx[id];
int mid=l+r>>1;
if(p<=mid) return query(ls,l,mid,p);
else return mx[ls]+query(rs,mid+1,r,p);
}
int main()
{
scanf("%d%d",&n,&typ);
build(1,0,N);
for(int r,i=1;i<=n;i++)
{
scanf("%d",&r);
dp[i]=query(1,0,N,r-1);
dp[i].mx++;
change(1,0,N,r,dp[i]);
}
ans=query(1,0,N,N);
printf("%d\n",ans.mx);
if(typ) printf("%d\n",ans.cnt);
return 0;
}
2018.11.1