UVALive 6947 Improvements(DP+树状数组)

forever97 posted @ 2016年8月23日 22:18 in 数据结构-树状数组 with tags 树状数组 单调DP , 499 阅读

 

【题目链接】

 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4959

 

【题目大意】

    给出一些飞船的位置,每艘飞船用绳子和序号相邻的飞船相连,现在去掉一些飞船,使得飞船之间的绳子不交叉。

 

【题解】

    绳子不交叉的情况就是可以有两条不交叉的路线来回,我们将位置序列转化为以位置为下标的编号序列,那么题目就转化为求先增后减的最长序列,那么,我们dp正反各求一遍LIS,保存在每个位置,将每个位置两次的答案求和,取最大值就是答案了。

 

【代码】

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=200005;
int n,x,a[N],c[N],up[N],down[N];
int add(int x,int num){while(x<N)c[x]=max(c[x],num),x+=x&-x;}
int query(int x){int s=0;while(x)s=max(s,c[x]),x-=x&-x;return s;}
int main(){
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++)scanf("%d",&x),a[x]=i;
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)add(a[i],up[i]=query(a[i])+1);
        memset(c,0,sizeof(c));
        for(int i=n;i;i--)add(a[i],down[i]=query(a[i])+1);
        int ans=0;
        for(int i=1;i<=n;i++)ans=max(up[i]+down[i]-1,ans);
        printf("%d\n",ans);
    }return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter