Longest Increasing Subsequence (dp+LIS)

链接:https://ac.nowcoder.com/acm/contest/1110/E
来源:牛客网
 

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld

题目描述

Bobo learned how to compute Longest Increasing Subsequence (LIS) in O(nlog⁡n)O(n \log n)O(nlogn) in ICPCCamp.

For those who did not attend ICPCCamp as Bobo,
recall LIS(a1,a2,…,an)\mathrm{LIS}(a_1, a_2, \dots, a_n)LIS(a1​,a2​,…,an​) is defined as f[1]2⊕f[2]2⊕⋯⊕f[n]2f[1]^2 \oplus f[2]^2 \oplus \dots \oplus f[n]^2f[1]2⊕f[2]2⊕⋯⊕f[n]2 where ⊕\oplus⊕ denotes the exclusive-or (XOR) and f is calculated as follows.

for i in [1, 2, ..., n]  f[i] = 1
for j in [1, 2, ..., i - 1]
    if a[j] < a[i] then
          f[i] = max(f[i], f[j] + 1)


Given sequence A=(a1,a2,…,an)A = (a_1, a_2, \dots, a_n)A=(a1​,a2​,…,an​), Bobo would like to find LIS(B1),LIS(B2),…,LIS(Bn)\mathrm{LIS}(B_1), \mathrm{LIS}(B_2), \dots, \mathrm{LIS}(B_n)LIS(B1​),LIS(B2​),…,LIS(Bn​)
where BiB_iBi​ is the sequence after removing the i-th element from A.

输入描述:

The input contains zero or more test cases and is terminated by end-of-file. For each test case:

The first line contains an integer n.
The second line contains n integers a1,a2,…,ana_1, a_2, \dots, a_na1​,a2​,…,an​.

* 2≤n≤50002 \leq n \leq 50002≤n≤5000
* 1≤ai≤n1 \leq a_i \leq n1≤ai​≤n
* The number of test cases does not exceed 10.

输出描述:

For each case, output n integers which denote LIS(B1),LIS(B2),…,LIS(Bn)\mathrm{LIS}(B_1), \mathrm{LIS}(B_2), \dots, \mathrm{LIS}(B_n)LIS(B1​),LIS(B2​),…,LIS(Bn​).

示例1

输入

复制

5
2 5 3 1 4

输出

复制

5 13 0 8 0

                先进行一边LIS,处理出表示以第i为结尾的最长上升子序列的长度f[i]数组。用vis[i]表示遍历到现在位置,长度为i的最长上升子序列的最小尾节点大小是多少。每次进行枚举删除节点K的时候的情况:假设f[i] == j但是vis[j]是一个比ai大的数,就表示删除的这个K影响了以i为结尾的最长上升子序列长度,f[i]在这里肯定会成为原来的f[i] - 1的大小。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5005;
int ans[maxn], arr[maxn], f[maxn];
void DP(int n) {
	ans[1] = arr[1];
	int len = 1; 
	f[1] = 1;
	for (int i = 2; i <= n; ++i) {
		if (arr[i] > ans[len])///严格上升
			ans[++len] = arr[i], f[i] = len;
		else {
			int pos = lower_bound(ans, ans + len, arr[i]) - ans;
			ans[pos] = arr[i]; f[i] = pos;
		}
	}
}
int vis[maxn];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n;
	while (cin >> n) {
		for (int i = 1; i <= n; i++) 
			cin >> arr[i];
		DP(n);
		for (int i = 1; i <= n; i++) {
			memset(vis, 0x3f, sizeof vis);
			vis[0] = -1; int res = 0;
			for (int j = 1; j < i; j++) {
				res ^= f[j] * f[j];
				vis[f[j]] = min(arr[j], vis[f[j]]);
			}
			for (int j = i + 1; j <= n; j++) {
				if (vis[f[j] - 1] < arr[j]) {
					res ^= f[j] * f[j];
					vis[f[j]] = min(vis[f[j]], arr[j]);
				}
				else {
					res ^= (f[j] - 1) * (f[j] - 1);
					vis[f[j] - 1] = min(vis[f[j] - 1], arr[j]);
				}
			}
			cout << res; if (i == n)cout << "\n"; else cout << " ";
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/chenshibo17/article/details/102165734