1. 程式人生 > >程式設計師的揹包 ZZULIOJ - 2485 離散化 dp lis | 樹狀陣列

程式設計師的揹包 ZZULIOJ - 2485 離散化 dp lis | 樹狀陣列

題解

經典的最長上升子序列問題
數值過大使用離散化處理 數值過多使用二分優化dp

AC程式碼

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 5e4 + 10;
int a[MAXN], d[MAXN], p[MAXN]; //d[i]以i為結尾的上升子序列長度 p[i]長度為i的最小結尾
vector<int> dz;

int
Dis(int v) { return lower_bound(dz.begin(), dz.end(), v) - dz.begin(); } int main() { #ifdef LOCAL //freopen("C:/input.txt", "r", stdin); #endif int N; cin >> N; for (int i = 1; i <= N; i++) scanf("%d", &a[i]), dz.push_back(a[i]); dz.push_back(-INF); sort(dz.begin(), dz.end()); dz.
erase(unique(dz.begin(), dz.end()), dz.end()); //數值過大 離散化 memset(p, 0x3f, sizeof(p)); p[0] = -INF; int ans = 0; for (int i = 1; i <= N; i++) { int k = lower_bound(p, p + N, Dis(a[i])) - p; //第一個大於等於當前值的長度 d[i] = k; p[k] = min(p[k], Dis(a[i])); //更新p陣列 ans = max(ans, d[i]); } cout << ans <<
endl; return 0; }

附帶最開始蒙比了寫的樹狀陣列解法

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 5e4 + 10;
int a[MAXN], c[MAXN];
vector<int> dz;

inline int Lowbit(int x) //x二進位制最低一位的1的值
{
	return x & -x;
}
void Add(int x, int v, int n) //修改位置 修改值 最大下標 使用Add初始化c陣列 要求下標範圍從1開始
{
	while (x <= n)
		c[x] = max(c[x], v), x += Lowbit(x); //x + Lowbit(x) 父節點
}
int Ask(int x) //查詢1~x字首和
{
	int res = 0;
	while (x)
		res = max(res, c[x]), x -= Lowbit(x); //x -= Lowbit(x) 兄弟節點
	return res;
}
int Dis(int v)
{
	return lower_bound(dz.begin(), dz.end(), v) - dz.begin();
}
int main()
{
#ifdef LOCAL
	//freopen("C:/input.txt", "r", stdin);
#endif
	int N;
	cin >> N;
	for (int i = 1; i <= N; i++)
		scanf("%d", &a[i]), dz.push_back(a[i]);
	dz.push_back(-INF);
	sort(dz.begin(), dz.end());
	dz.erase(unique(dz.begin(), dz.end()), dz.end());
	int ans = 0;
	for (int i = 1; i <= N; i++)
	{
		int k = Dis(a[i]); //離散化
		int res = Ask(k - 1); //查詢小於k的最長長度
		Add(k, res + 1, dz.size()); //記錄當前長度
		ans = max(ans, res + 1);
	}
	cout << ans << endl;

	return 0;
}