SPOJ

cdq分治,dp(i)表示以i为结尾的最长LIS,那么dp的递推是依赖于左边的。

因此在分治的时候需要利用左边的子问题来递推右边。

(345ms? 区间树TLE

/*********************************************************
*            ------------------                          *
*   author AbyssFish                                     *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
#include<numeric>
using namespace std;

const int MAX_N = 100000+5;


int dp[MAX_N];
int x[MAX_N], y[MAX_N];
int ys[MAX_N];
int id[MAX_N];
int N;

int ns;

int *cur;
bool cmp(int a,int b)
{
    return cur[a] < cur[b] || (cur[a] == cur[b] && a > b);//这是为了保证严格的单调性
}

int compress(int *r, int *dat, int *a, int n)
{
    for(int i = 0; i < n; i++){
        r[i] = i;
    }
    cur = dat;
    sort(r,r+n,cmp);
    a[r[0]] = 1;
    for(int i = 1; i < n; i++){
        int k = r[i], p = r[i-1];
        a[k] = dat[k] == dat[p]?a[p]:a[p]+1;
    }
    return a[r[n-1]];
}

int C[MAX_N];

void add(int yi,int d)
{
    while(yi <= ns){
        C[yi] = max(C[yi],d);
        yi += yi&-yi;
    }
}

int mx_pfx(int yi)
{
    int re = 0;
    while(yi > 0){
        re = max(C[yi],re);
        yi &= yi-1;
    }
    return re;
}

void clr(int yi)
{
    while(yi <= ns){
        C[yi] = 0;
        yi += yi&-yi;
    }
}

void dv(int l, int r)
{
    if(r-l <= 1){
        dp[l]++;
    }
    else {
        int md = (l+r)>>1;
        dv(l,md);

        for(int i = l; i < r; i++) id[i] = i;
        sort(id+l,id+r,cmp); //x维度

        for(int i = l; i < r; i++){
            int k = id[i];
            if(k < md){ //position 维度
                add(ys[k],dp[k]); //BIT下标是 y维度
            }
            else {
                //查询位置前保证了BIT里的元素, 位置md之前,x严格小于待查元素
                dp[k] = max(dp[k], mx_pfx(ys[k]-1));//y严格小于待查元素的最大dp值
            }
        }

        for(int i = l; i < r; i++){
            if(id[i] < md)
                clr(ys[id[i]]);
        }
        dv(md,r);
    }
}

void solve()
{
    scanf("%d",&N);
    for(int i = 0; i < N; i++){
        scanf("%d%d",x+i,y+i);
    }
    ns = compress(id,y,ys,N);
    cur = x;
    dv(0,N);
    printf("%d
",*max_element(dp,dp+N));
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/5011307.html