HDU 5141 LIS Again LIS变形+BIT

来源:互联网 发布:js短路逻辑 编辑:程序博客网 时间:2024/06/05 19:54

HDU 5141
题意:给出长度为n的序列a,序列a的LIS长度为L,问有多少个区间[i,j]有长度为L的LIS.
n<=1e5,a[i]<=1e9.

枚举右端点R 然后找到最右边的一个L 使得[L,R]的子序列有长度为L的LIS. 则区间[1..L,R]都有长度为LIS的子序列.
先算dp[i] 以i结尾的LIS长度 和 rg[i]: 以i结尾子序列长度为LIS时最右的左端点 离散化后用BIT维护该段LIS最大值和最右的左端点

现在从小到大枚举区间的右端点i, 维护k<=i,dp[k]==L中最右的左端点pre,则此时左端点L可以取[1..pre]

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=2e5+5,inf=0x3f3f3f3f;int n,a[N],c[2][N];int dp[N],rg[N],mx,res;vector<int> v;void discrete(){    sort(v.begin(),v.end());    v.erase(unique(v.begin(),v.end()),v.end());    for(int i=1;i<=n;i++)        a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;}int lowbit(int x){return x&-x;}void query(int x){    for(int i=x;i>0;i-=lowbit(i))    {        if(c[0][i]>mx)            mx=c[0][i],res=c[1][i];        else if(c[0][i]==mx&&c[1][i]>res)            res=c[1][i];    }}void update(int x,int val,int rg){    for(int i=x;i<N;i+=lowbit(i))    {        if(c[0][i]<val)            c[0][i]=val,c[1][i]=rg;        else if(c[0][i]==val&&c[1][i]<rg)            c[1][i]=rg;    }}int main(){    while(cin>>n)    {        int L=0;        v.clear();        memset(c,0,sizeof(c));        for(int i=1;i<=n;i++)            scanf("%d",&a[i]),v.push_back(a[i]);        discrete();        for(int i=1;i<=n;i++)        {            mx=0,res=0;            query(a[i]-1);            dp[i]=mx+1;            rg[i]=res?res:i;         //   cout<<i<<' '<<dp[i]<<' '<<rg[i]<<endl;            update(a[i],dp[i],rg[i]);            L=max(L,dp[i]);        }       // cout<<L<<endl;        ll ans=0;        int pre=0;        for(int i=1;i<=n;i++)        {            if(dp[i]==L)                pre=max(pre,rg[i]);            ans=(ans+pre);        }        cout<<ans<<endl;    }    return 0;}


原创粉丝点击