首页 > 代码库 > HDU 5141 LIS again

HDU 5141 LIS again

Problem Description
A numeric sequence of ai is ordered if a1<a2<<aN. Let the subsequence of the given numeric sequence (a1,a2,,aN) be any sequence (ai1,ai2,,aiK), where 1i1<i2<<iKN. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, eg. (1, 7), (3, 4, 8) and many others. 
S[ i , j ] indicates ( ai,ai+1,ai+2,,aj) .
Your program, when given the numeric sequence (a1,a2,,aN), must find the number of pair ( i, j) which makes the length of the longest ordered subsequence of S[ i , j ] equals to the length of the longest ordered subsequence of (a1,a2,,aN).
 

Input
Multi test cases (about 100), every case occupies two lines, the first line contain n, then second line contain n numbers a1,a2,,aN separated by exact one space. 
Process to the end of file.

[Technical Specification]
1n100000
0ai1000000000
 

Output
For each case,.output the answer in a single line.
 

Sample Input
3 1 2 3 2 2 1
 

Sample Output
1 3
 

Source
BestCoder Round #21


这道题真心不会,看了题解和别人博客,问了bin巨,搞了半天才理解。

树状数组优化的是求解LIS和LIS最大的时候最靠右的位置。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<bitset>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn = 100005;
const int mod = 1000000007;
int pos1[maxn],pos2[maxn],dp[maxn];
int a[maxn<<2],b[maxn<<2],sum[maxn][2],cnt,n;//sum[i][0]记录到i并且以i为结尾的最大的LIS的值,sum[i][0]记录LIS最大的条件下LIS最靠右的起始点的位置
int len,ans,pos;
void work()
{
    sort(b,b+cnt);
    cnt=unique(b,b+cnt)-b;//b数组的大小
    REP(i,n)   a[i]=lower_bound(b,b+cnt,a[i])-b+1;
}
int lowbit(int x)  
{  
    return x&(-x);  
} 
void add(int x,int s,int p)
{
    while(x<=cnt)
    {
        if(sum[x][0]<s)
        {
            sum[x][0]=s;
            sum[x][1]=p;
        }
        if(sum[x][0]==s&&sum[x][1]<p)
            sum[x][1]=p;
        x+=lowbit(x);
    }
} 
void query(int x)
{
    while(x)
    {
        if(ans<sum[x][0])
        {
            pos=sum[x][1];
            ans=sum[x][0];
        }
        if(ans==sum[x][0]&&pos<sum[x][1])
            pos=sum[x][1];
        x-=lowbit(x);
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        cnt=0;
        REP(i,n)   
        {
            scanf("%I64d",&a[i]);
            b[cnt++]=a[i];
        }
        CLEAR(sum,0);
        work();
        len=0;
        REP(i,n)
        {
            ans=0;
            query(a[i]-1);
            dp[i]=ans+1;
            if(ans==0)
                pos1[i]=i;
            else   pos1[i]=pos;
            add(a[i],dp[i],pos1[i]);
            len=max(len,dp[i]);
        }
        int pre=n;
        for(int i=n-1;i>=0;i--)
        {
            if(dp[i]==len)
            {
                pos2[i]=pre-1;
                pre=i;
            }
        }
        LL s=0;
        for(int i=0;i<n;i++)
        {
            if(dp[i]==len)
                s+=(LL)(pos1[i]+1)*(pos2[i]+1-i);
        }
        printf("%I64d\n",s);
    }
    return 0;
}



HDU 5141 LIS again