SPOJ LIS2

题目链接  LIS2

经典的三维偏序问题。

考虑$cdq$分治。

不过这题的顺序应该是

$cdq(l, mid)$

$solve(l, r)$

$cdq(mid+1, r)$

因为有个$DP$。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

const int N = 1e5 + 10;

struct node{
	int x, y, z;
	int num;
	void scan()  { scanf("%d%d", &y, &z);}
	void print() { printf("%d %d %d
", x, y, z);}
	friend bool operator < (const node &a, const node &b){
		return a.y == b.y ? a.z < b.z : a.y < b.y;
	}
} p[N], q[N];

int a[N], b[N];
int n;
int cnt;
int c[N];
int ans;

void update(int x, int val){
	for (; x <= n; x += x & -x) c[x] = max(c[x], val);
}

int query(int x){
	int ret = 0;
	for (; x ; x -= x & -x) ret = max(ret, c[x]);
	return ret;
}

void recover(int x){
	for (; x <= n; x += x & -x) c[x] = 0;
}

bool cmp(const node &a, const node &b){
	return a.x < b.x;
}

void cdq(int l, int r){
	if (l == r) return;
	int mid = (l + r) >> 1;
	cdq(l, mid);
	sort(p + l, p + mid + 1);
	sort(p + mid + 1, p + r + 1);
	int j = l;
	for (int i = mid + 1; i <= r; ++i){
		for (; j <= mid && p[j].y < p[i].y; ++j){
			update(p[j].z, p[j].num);
		}

		p[i].num = max(p[i].num, query(p[i].z - 1) + 1);
	}

	rep(i, l, mid) recover(p[i].z);
	sort(p + mid + 1, p + r + 1, cmp);
	cdq(mid + 1, r);

}

int main(){

	scanf("%d", &n);
	rep(i, 1, n) p[i].scan();
       	rep(i, 1, n) a[i] = p[i].y;
	rep(i, 1, n) p[i].num = 1;    

	sort(a + 1, a + n + 1);
	cnt = unique(a + 1, a + n + 1) - a - 1;
	rep(i, 1, n) p[i].y = lower_bound(a + 1, a + cnt + 1, p[i].y) - a;

	rep(i, 1, n) a[i] = p[i].z;
	sort(a + 1, a + n + 1);
	cnt = unique(a + 1, a + n + 1) - a - 1;
	rep(i, 1, n) p[i].z = lower_bound(a + 1, a + cnt + 1, p[i].z) - a;
	
	rep(i, 1, n) p[i].x = i;

	cdq(1, n);
	ans = 0;
	rep(i, 1, n) ans = max(ans, p[i].num);
	printf("%d
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/cxhscst2/p/7652513.html