HDU 5489 Removed Interval

题意:求一段序列中删掉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;
}

  

时间: 2024-12-16 16:48:12

HDU 5489 Removed Interval的相关文章

HDU 5489 Removed Interval (LIS变形)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5489 给你n个数,要删去其中连续的L个,问你删去之后的LIS最大是多少? 我们先预处理出以i下标为开头的LIS,存到数组中. 然后可以枚举长为L的区间,每次移动,左边增加一个,右边删除一个. 最长上升子序列长度 = 窗口右边以右边第一个元素开头的最长上升子序列 + 窗口左边最大元素小于窗口右边第一个元素的最长上升子序列. 比如 1 2 [4 3] 2 3 5  ,  LIS = 3 + 1 = 4

【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间),使得剩余的数最长上升子序列(LIS)最长. 题目思路: [二分][最长上升子序列] 首先,假设去掉[i,i+m-1]这L个数,剩余的LIS长度为max(i左端最后一个不大于a[i+m]的LIS长度+a[i+m]开始到最后的LIS长度). 所以,我们从n到1逆向先求最长下降子序列的长度f[i],就可以知

HDU 5489 Removed Interval 2015 ACM/ICPC Asia Regional Hefei Online

定义f[i]表示以i为开头往后的最长上升子序列,d[i]表示以i为结尾的最长上升子序列. 先nlogn算出f[i], 从i-L开始枚举f[i],表示假设i在LIS中得到的最长上升子序列,往[0,i-L)里找到满足ai>aj中dj值最大的.用dj+f[i]更新. 但是这样会少考虑一种情况,即i-L以后都不在最终的答案里面,这样一定是以[0~i-L)中的某个结尾的,所以还要用d[j]去更新答案. #include<bits/stdc++.h> using namespace std; con

HDU 5489 Removed Interval (LIS,变形)

题意: 给出一个n个元素的序列,要求从中删除任一段长度为L的连续子序列,问删除后的LIS是多少?(n<=10w, L<=n ,元素可能为负) 思路: 如果会O(nlogn)求普通LIS的算法,这道题将变得很简单. 首先按照求LIS的思路,当扫到元素a[i]并完成操作后,a[1->i]就是一段已经处理完成的序列,假设a[i+1]->a[i+L]这一段是将要删去的,那么将分成两段:a[0]->a[i]和a[i+L+1]->a[n]. 假设后一段以a[i+L+1]开头,而前段

Hdu 5489 合肥网络赛 1009 Removed Interval

跳跃式LIS(nlogn),在普通的转移基础上增加一种可以跨越一段距离的转移,用一颗新的树状数组维护,同时,我们还要维护跨越完一次后面的转移,所以我用了3颗树状数组.. 比赛的时候一句话位置写错了,然后就...雪崩 呆马: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <vector> 6 #include

hdu 5489——

#include<bits/stdc++.h> using namespace std; const int maxn=1e6+200; const int INF = 0x3f3f3f3f; int a[maxn],b[maxn],endminv[maxn]; int dp[maxn]; int BinSearch(int l,int r,int key,int typ){ int md; if(typ==0){ while(l<r){ md=(l+r)/2; if(endminv[m

补题列表

上海网络赛: HDU 5468 Puzzled Elena HDU 5469 Antonidas HDU 5473 There was a kingdom 合肥网络赛: HDU 5487 Difference of Languages HDU 5486 Difference of Clustering HDU 5489 Removed Interval HDU 5492 Find a path HDU 5493 Queue 弱校联萌Day1: B. Carries D. Vertex Cover

2015 ACM/ICPC Asia Regional Hefei Online

1001 Monitor the Alpacas 1002 The Relationship in Club 1003 Difference of Clustering 1004 Difference of Languages 1005 Shape 1006 Removed Interval 1007 Simple Matrix 1008 The Next 1009 Find a path 1010 Queue

HDU5489 LIS变形

Removed Interval Problem Description Given a sequence of numbers A=a1,a2,…,aN , a subsequence b1,b2,…,bk of A is referred as increasing if b1<b2<…<bk . LY has just learned how to find the longest increasing subsequence (LIS).Now that he has to se