http://www.lydsy.com/JudgeOnline/upload/201610/test8888.rar
降雷皇哈蒙很喜欢雷电,他想找到神奇的电光。哈蒙有n条导线排成一排,每条导线有一个电阻值,神奇的电光只
能从一根导线传到电阻比它大的上面,而且必须从左边向右传导,当然导线不必是连续的。哈蒙想知道电光最多能
通过多少条导线,还想知道这样的方案有多少。
http://www.lydsy.com/JudgeOnline/upload/201610/test8888.rar
降雷皇哈蒙很喜欢雷电,他想找到神奇的电光。哈蒙有n条导线排成一排,每条导线有一个电阻值,神奇的电光只
能从一根导线传到电阻比它大的上面,而且必须从左边向右传导,当然导线不必是连续的。哈蒙想知道电光最多能
通过多少条导线,还想知道这样的方案有多少。
5 1
1 3 2 5 4
3
4
题解:dp+线段树。
dp 求最长上升子序列 f[i]=max{f[j]}+1 (j
第二问的话,其实还是可以利用线段树。
g[i]表示以i结尾的最长公共子序列的方案数。
g[i]=sigma g[j] f[i]=f[j]+1,j
我们可以以f[i]为第一关键字,位置i为第二关键字。
然后统计f[i]=x的时候,设两个指针分别指在f[i]==x-1的开头,和f[i]==x的开头,不断的往后扫,保证计算答案的时候位置在他之前的都已经加入权值线段树。
每次用完打lazy标记,清线段树即可。
#include
#include
#include
#include
#include
#define N 100003
#define p 123456789
using namespace std;
int a1[N],b[N],c[N],cnt,n,g[N],p1[N],f[N];
struct data
{
int h,pos,x;
}a[N];
int tr[N*4],delta[N*4],sum[N*4];
int cmp(int x,int y)
{
return a1[x]rr) return 0;
if (ll<=l&&r<=rr) return tr[now];
int mid=(l+r)/2; int ans=0;
if (ll<=mid) ans=max(ans,qjmax(now<<1,l,mid,ll,rr));
if (rr>mid) ans=max(ans,qjmax(now<<1|1,mid+1,r,ll,rr));
return ans;
}
void update1(int now)
{
sum[now]=(sum[now<<1]+sum[now<<1|1])%p;
}
void pushdown(int now)
{
if (delta[now]) {
delta[now]=0;
delta[now<<1]=1; delta[now<<1|1]=1;
sum[now<<1]=0; sum[now<<1|1]=0;
}
}
void pointchange(int now,int l,int r,int x,int v)
{
if (l==r) {
sum[now]=(sum[now]+v)%p;
return ;
}
int mid=(l+r)/2;
pushdown(now);
if (x<=mid) pointchange(now<<1,l,mid,x,v);
else pointchange(now<<1|1,mid+1,r,x,v);
update1(now);
}
int qjsum(int now,int l,int r,int ll,int rr)
{
if (ll>rr) return 0;
if (ll<=l&&r<=rr) return sum[now]%p;
int mid=(l+r)/2;
pushdown(now); int ans=0;
if (ll<=mid) ans=(ans+qjsum(now<<1,l,mid,ll,rr))%p;
if (rr>mid) ans=(ans+qjsum(now<<1|1,mid+1,r,ll,rr))%p;
return ans%p;
}
int main()
{
freopen("hamon.in","r",stdin);
freopen("my.out","w",stdout);
int t;
scanf("%d%d",&n,&t);
for (int i=1;i<=n;i++) scanf("%d",&a1[i]),b[i]=i;
sort(b+1,b+n+1,cmp);
for (int i=1;i<=n;i++)
if(a1[b[i]]!=a1[b[i-1]])
c[b[i]]=++cnt;
else c[b[i]]=cnt;
change(1,1,n,c[1],1);
f[1]=1;
for (int i=2;i<=n;i++) {
f[i]=qjmax(1,1,n,1,c[i]-1)+1;
change(1,1,n,c[i],f[i]);
}
for (int i=1;i<=n;i++) a[i].x=f[i],a[i].h=c[i],a[i].pos=i;
sort(a+1,a+n+1,cmp1);
if (t!=1) {
printf("%d\n",a[n].x);
return 0;
}
int i=1;
int ans=0;
while (a[i].x==1)
{
g[a[i].pos]=1;
if (a[i].x==a[n].x) ans+=g[a[i].pos];
i++;
}
cnt=0;
for (int i=1;i<=n;i++)
if (a[i].x!=a[i-1].x) p1[++cnt]=i;
for (int i=2;i<=cnt;i++)
{
delta[1]=1; sum[1]=0;
int j=p1[i-1]; int k=p1[i];
while (a[k].x==i) {
while (a[j].pos