代码 RE 求调
查看原帖
代码 RE 求调
908514
DHT666楼主2024/8/23 16:21
#include<bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10, inf = 2e9;

struct node {
	int l, r, v;
}tree[N * 8];

int n;
int a[N], c[N];
int f[N], m[N];

void push_up(int u) {
	tree[u].v = tree[u << 1].v + tree[u << 1 | 1].v;
}

void build(int u,int l,int r) {
	tree[u].l = l, tree[u].r = r;
	if(l == r) {
		tree[u].v = 1;
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	push_up(u);
}

void modify(int u,int x,int d) {
	if(tree[u].l == tree[u].r) {
		tree[u].v = d;
		return;
	}
	int mid = tree[u].l + tree[u].r >> 1;
	if(x <= mid) modify(u << 1, x, d);
	else modify(u << 1 | 1, x, d);
	push_up(u);
}

int query(int u,int x) {
//	cout << tree[u].l << " " << tree[u].r << endl;
	if(tree[u].l == tree[u].r) {
//		cout << "dsd:" << tree[u].l << endl;
		return tree[u].l;
	}
	int mid = tree[u].l + tree[u].r >> 1;
	if(x <= tree[u << 1].v) return query(u << 1, x);
	else query(u << 1 | 1, x - tree[u << 1].v);
}

signed main() {
	scanf("%lld", &n);
	for(int i = 1;i <= n;i++) {
		scanf("%lld", &a[i]);
	}
	
	build(1, 1, n);
	
	for(int i = n;i >= 1;i--) {
		int tot = query(1, a[i] + 1);
//		cout << tot << " " << a[i] + 1 << endl;
		c[tot] = i;
		modify(1, tot, 0);
	}
	
//	for(int i = 1;i <= n;i++) {
//		cout << c[i] << " ";
//	}
//	cout << endl;
	
	for(int i = 1;i <= n;i++) {
		m[c[i]] = i;
		f[i] = inf;
	} 
	
	int len = 0;
	f[0] = 0;
	for(int i = 1;i <= n;i++) {
		int l = 0, r = len;
		while(l < r) {
			int mid = l + r + 1 >> 1;
			if(f[mid] <= m[i]) l = mid;
			else r = mid - 1;
		}
		if(l == len) f[++len] = m[i];
		else f[l + 1] = min(f[l + 1], m[i]);
		printf("%lld\n", len);
	}
	
	return 0;
}

主要思路是用线段树倒序处理插入操作,然后正常二分 LIS 求答案。

2024/8/23 16:21
加载中...