luogu4093 [HEOI2016/TJOI2016]序列

Posted poorpool

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu4093 [HEOI2016/TJOI2016]序列相关的知识,希望对你有一定的参考价值。

因为一个变化只会变化一个值,所以
\(dp[i]=max(dp[j])+1,j<i,maxval_j \leq a[i], a[j] \leq minval_i\)
发现跟二维数点问题挺像,树状数组套线段树爽一爽。

#include <iostream>
#include <cstdio> 
using namespace std;
int n, m, zdz[100005], zxz[100005], a[100005], uu, vv, cnt, dp[100005], ans, rot[100005];
struct Node{
    int l, r, zdz;
}nd[9000005];
int lb(int x){
    return x&-x;
}
void insert(int &o, int l, int r, int x, int k){
    if(!o)  o = ++cnt;
    if(l==r)    nd[o].zdz = max(nd[o].zdz, k);
    else{
        int mid=(l+r)>>1;
        if(x<=mid)  insert(nd[o].l, l, mid, x, k);
        if(mid<x)   insert(nd[o].r, mid+1, r, x, k);
        nd[o].zdz = max(nd[nd[o].l].zdz, nd[nd[o].r].zdz);
    }
}
int query(int o, int l, int r, int x, int y){
    if(!o)  return 0;
    if(l>=x &&r<=y) return nd[o].zdz;
    else{
        int mid=(l+r)>>1;
        int re=0;
        if(x<=mid)  re = max(re, query(nd[o].l, l, mid, x, y));
        if(mid<y)   re = max(re, query(nd[o].r, mid+1, r, x, y));
        return re;
    }
}
int main(){
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i]);
        zdz[i] = zxz[i] = a[i];
    }
    for(int i=1; i<=m; i++){
        scanf("%d %d", &uu, &vv);
        zdz[uu] = max(zdz[uu], vv);
        zxz[uu] = min(zxz[uu], vv);
    }
    for(int i=1; i<=n; i++){
        for(int j=zxz[i]; j; j-=lb(j))
            dp[i] = max(dp[i], query(rot[j], 1, 100000, 1, a[i]));
        dp[i]++;
        ans = max(ans, dp[i]);
        for(int j=a[i]; j<=100000; j+=lb(j))
            insert(rot[j], 1, 100000, zdz[i], dp[i]);
    }
    cout<<ans<<endl;
    return 0;
}

以上是关于luogu4093 [HEOI2016/TJOI2016]序列的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P4093 [HEOI2016/TJOI2016]序列

P4093[HEOI2016/TJOI2016]序列

BZOJ4553/洛谷P4093 [HEOI2016/TJOI2016]序列 动态规划 CDQ分治

题解 P4093 [HEOI2016/TJOI2016]序列

洛谷P4093 [HEOI2016/TJOI2016]序列

洛谷 P4093 [HEOI2016/TJOI2016]序列