loj2056 「TJOI / HEOI2016」序列

当年我还没学cdq的时候在luogu上写过树套树的代码orzzz
ref

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int n, m, uu, vv, dp[100005], c[100005];
struct Node{
	int val, zxz, zdz, idx;
}nd[100005], tmp[100005];
bool cmpzxz(Node x, Node y){
	return x.zxz<y.zxz;
}
bool cmpidx(Node x, Node y){
	return x.idx<y.idx;
}
int lb(int x){
	return x&-x;
}
void add(int x, int v){
	for(; x<=100000; x+=lb(x))
		c[x] = max(c[x], v);
}
int query(int x){
	int re=0;
	for(; x; x-=lb(x))
		re = max(re, c[x]);
	return re;
}
void clr(int x){
	for(; x<=100000; x+=lb(x))
		c[x] = 0;
}
void cdq(int l, int r){
	if(l==r)	return ;
	int mid=(l+r)>>1;
	cdq(l, mid);
	sort(nd+mid+1, nd+r+1, cmpzxz);
	int qaq=l;
	for(int i=mid+1; i<=r; i++){
		while(qaq<=mid && nd[qaq].val<=nd[i].zxz){
			add(nd[qaq].zdz, dp[nd[qaq].idx]);
			qaq++;
		}
		dp[nd[i].idx] = max(dp[nd[i].idx], query(nd[i].val)+1);
	}
	for(int i=l; i<qaq; i++)	clr(nd[i].zdz);
	sort(nd+mid+1, nd+r+1, cmpidx);
	cdq(mid+1, r);
	int jj=l, kk=mid+1;
	for(int i=l; i<=r; i++)
		if(jj<=mid && (kk>r || nd[jj].val<=nd[kk].val))	tmp[i] = nd[jj++];
		else	tmp[i] = nd[kk++];
	for(int i=l; i<=r; i++)
		nd[i] = tmp[i];
}
int main(){
	cin>>n>>m;
	for(int i=1; i<=n; i++){
		scanf("%d", &nd[i].val);
		nd[i].zdz = nd[i].zxz = nd[i].val;
		nd[i].idx = i;
		dp[i] = 1;
	}
	for(int i=1; i<=m; i++){
		scanf("%d %d", &uu, &vv);
		nd[uu].zdz = max(nd[uu].zdz, vv);
		nd[uu].zxz = min(nd[uu].zxz, vv);
	}
	cdq(1, n);
	int ans=0;
	for(int i=1; i<=n; i++)
		ans = max(ans, dp[i]);
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/8989181.html