码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5489 Removed Interval

时间:2015-09-27 20:11:16      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:

题意:求一段序列中删掉L个连续元素后的LIS。

 

解法:我的想法很复杂= =怎么说呢……首先用nlogn的方法求LIS得到的序列dp的第i项的意义为上升子序列所有长度为i的序列结尾元素的最小值,那么先倒着用nlogn的方法求一遍最长下降子序列记为dp1,记录每一步怎么更新的dp1,再正着求一遍最长上升子序列,每次看a[i]的时候二分的在i+k到结尾的dp1中找第一个比a[i]大的数设为dp1[pos],所以当前枚举的答案即为以a[i]作为结尾的最长上升子序列+后一段以dp1[pos]开头的最长上升子序列……枚举1~n-l,就可以得到答案了TUT……

总之很艰辛……二分废又得找队友帮忙手写二分什么的……

另一队的人提出用线段树算LIS……真·大神= =不懂怎么转移的方程……

 

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
int inf = 1000000005;
using namespace std;
int a[100005];
LL dp1[100005], dp2[100005];
struct node
{
    bool isnew;
    int pos;
    int pre;
}note[100005];
bool cmp(int a, int b)
{
    return a > b;
}
template <class T>
int rupper_bound(T *a, T *end, T key) {
    int n = end - a;
    if(n == 0) return INT_MAX;
    if (a[n-1] > key) return n-1;
    if (a[0] <= key) return INT_MAX;
    int l = 0, r = n - 1;
    while(r - l > 1) {
        int m = (l+r) >> 1;
        if (a[m] > key) l = m;
        else r = m;
    }
    return l;
}
int main()
{
    int T;
    scanf("%d", &T);
    int cse = 1;
    while(T--)
    {
        int n, l;
        scanf("%d%d", &n, &l);
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        a[0] = -inf;
        int max1 = 0, max2 = 0;
        for(int i = n; i > l; i--)
        {
            int pos = upper_bound(dp1, dp1 + max1, a[i], cmp) - dp1;
            if(pos == max1)
            {
                note[i].isnew = 1;
                note[i].pos = max1;
                dp1[max1++] = a[i];
            }
            else
            {
                note[i].isnew = 0;
                note[i].pos = pos;
                note[i].pre = dp1[pos];
                dp1[pos] = a[i];
            }
        }
        int ans = 0;
        LL s = -inf;
        int len = 0;
        for(int i = 1; i <= n - l + 1; i++)
        {
            int pos = rupper_bound(dp1, dp1 + max1, s);
            if(pos == INT_MAX) ans = max(ans, len);
            else ans = max(ans, pos + 1 + len);
            int x = upper_bound(dp2, dp2 + max2, a[i]) - dp2;
            if(x == max2)
            {
                len = max2 + 1;
                s = a[i];
                dp2[max2++] = a[i];
            }
            else
            {
                len = x + 1;
                s = a[i];
                dp2[x] = a[i];
            }
            if(note[i + l].isnew)
            {
                max1--;
            }
            else
            {
                dp1[note[i + l].pos] = note[i + l].pre;
            }
        }
        printf("Case #%d: %d\n", cse++, ans);
    }
    return 0;
}

  

HDU 5489 Removed Interval

标签:

原文地址:http://www.cnblogs.com/Apro/p/4842540.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!