HDU 6642 Three Investigators

HDU 6642 Three Investigators

前置知识:

一个序列构造的杨表,前i列的长度和为\(K-LIS\)的长度。

\(K-LIS\)为最长的子序列满足其\(LIS\leq k\)

运算符取反,\(K-LDS\)也就是杨表前\(k\)行的和。

而这个问题也就是要求\(K-LDS\)的长度。

所以直接用\(map\)模拟杨表的暴力插入即可,时间复杂度\(O(N2^5\log N)\)

/**
 *    author:  gary
 *    created: 07.11.2021 17:12:44
**/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define rep(a,b) for(int a=0;a<b;++a)
#define LL long long
#define PB push_back
#define POB pop_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
const int MAXN=100000+1;
int n,a[MAXN];
LL cnt[5];
map<int,LL> M[5];
void insert(int i,int x,int c){
    if(i==5) return ;
    auto ite=M[i].upper_bound(x);
    if(ite==M[i].end()){
        M[i][x]+=c;
        cnt[i]+=c;
        return ;
    }
    mp Tmp=*ite;
    if(Tmp.SEC==c){
        M[i].erase(ite);
        M[i][x]+=c;
        insert(i+1,Tmp.FIR,c);
        return ;
    }
    if(Tmp.SEC<c){
        M[i].erase(ite);
        M[i][x]+=Tmp.SEC;
        insert(i+1,Tmp.FIR,Tmp.SEC);
        insert(i,x,c-Tmp.SEC);
    }
    else{
        M[i][x]+=c;
        M[i][Tmp.FIR]-=c;
        insert(i+1,Tmp.FIR,c);
    }
}
void solve(){
    scanf("%d",&n);
    rb(i,1,n) scanf("%d",&a[i]);
    rep(i,5) M[i].clear(),cnt[i]=0;
    rb(i,1,n){
        insert(0,a[i],a[i]);
        printf("%lld",cnt[0]+cnt[1]+cnt[2]+cnt[3]+cnt[4]);
        if(i!=n){
            putchar(' ');
        }
    }
    puts("");
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--) solve();
    return 0;
}
posted @ 2021-11-07 22:59  WWW~~~  阅读(75)  评论(0)    收藏  举报