Nonsense Time【2019 HDU多校6】【动态维护最长上生子序列LIS】

HDU-6635 题目链接



  比赛的时候想的是存在一条链上,去判断是否在这条LIS链上,在就更新,不在就继续继承答案,然后就这样T掉了,因为我真的用了一条Dijkstra的链……

  这里的时间复杂度为什么是O(N * sqrt(N) * log(N))呢,是因为这里给出的数都是随机的,并且在一个一个添加进来的数也是随机的,表示的是(出题人并没有出强数据),讲题解的人如是说到。

  然后在这里,就是去维护是否在这条LIS链上即可,在就更新,不在就不更新,只是这里的Code写起来需要谨慎一点,我的线段树被卡掉了,然后就去写了树状数组来维护这个,然后注意维护的关系。

  我维护的是树状数组上查最大的F(),然后存的是对应点的值。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 5e4 + 7;
int N, a[maxN], re[maxN], p[maxN], pre[maxN], nex[maxN], bit[maxN], F[maxN], out[maxN], las[maxN];
bool used[maxN];
inline void update(int x)
{
    int cop = x;
    while(x <= N)
    {
        if(F[bit[x]] < F[cop]) bit[x] = cop;
        x += lowbit(x);
    }
}
inline int query(int x)
{
    int ans = 0;
    while(x)
    {
        if(F[ans] < F[bit[x]]) ans = bit[x];
        x -= lowbit(x);
    }
    return ans;
}
inline int ex_change()
{
    int maxx = 0, id = 0;
    for(int i=nex[0], u; i<=N; i=nex[i])
    {
        used[i] = false;
        u = query(a[i]);
        F[a[i]] = F[u] + 1;
        las[i] = re[u];
        if(F[a[i]] > maxx) { maxx = F[a[i]]; id = i; }
        update(a[i]);
    }
    for(int i=1; i<=N; i++) bit[i] = F[i] = 0;
    for(int i=id; i; i=las[i]) used[i] = true;
    return maxx;
}
int main()
{
    int Cas; scanf("%d", &Cas);
    while(Cas--)
    {
        scanf("%d", &N);
        for(int i=1; i<=N; i++) { scanf("%d", &a[i]); re[a[i]] = i; }
        for(int i=1; i<=N; i++) scanf("%d", &p[i]);
        for(int i=0; i<=N; i++) { pre[i] = i - 1; nex[i] = i + 1; }
        for(int i=1; i<=N; i++) { bit[i] = 0; used[i] = false; }
        int now = ex_change();
        for(int i=N, pos; i>=1; i--)
        {
            pos = p[i];
            out[i] = now;
            pre[nex[pos]] = pre[pos];
            nex[pre[pos]] = nex[pos];
            if(used[pos]) now = ex_change();
        }
        for(int i=1; i<=N; i++) printf("%d%c", out[i], i == N ? '\n' : ' ');
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值