链接: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(nlogn)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;
}