Hills And Valleys
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 146 Accepted Submission(s): 47
Special Judge
Problem Description
Tauren has an integer sequence A of length n (1-based). He wants you to invert an interval [l,r] (1≤l≤r≤n) of A (i.e. replace Al,Al+1,⋯,Ar with Ar,Ar−1,⋯,Al) to maximize the length of the longest non-decreasing subsequence of A. Find that maximal length and any inverting way to accomplish that mission.
A non-decreasing subsequence of A with length m could be represented as Ax1,Ax2,⋯,Axm with 1≤x1<x2<⋯<xm≤n and Ax1≤Ax2≤⋯≤Axm.
Input
The first line contains one integer T, indicating the number of test cases.
The following lines describe all the test cases. For each test case:
The first line contains one integer n.
The second line contains n integers A1,A2,⋯,An without any space.
1≤T≤100, 1≤n≤105, 0≤Ai≤9 (i=1,2,⋯,n).
It is guaranteed that the sum of n in all test cases does not exceed 2⋅105.
Output
For each test case, print three space-separated integers m,l and r in one line, where m indicates the maximal length and [l,r] indicates the relevant interval to invert.
Sample Input
2 9 864852302 9 203258468
Sample Output
5 1 8 6 1 2
Hint
In the first example, 864852302 after inverting [1, 8] is 032584682, one of the longest non-decreasing subsequences of which is 03588. In the second example, 203258468 after inverting [1, 2] is 023258468, one of the longest non-decreasing subsequences of which is 023588.
传送门:HDU-6357
题意:给出一个只有0~9的序列,可以选择翻转一个区间,要求求出最大的不下降子序列长度,并输出翻转的区间。
题解:多校时搞了个N*10^3的算法不敢写。。。结果没优化常数就780ms过了。。。
设dp[i][x][y][z][0/1/2]为,翻转的区间中最大值为x,最小值为y,当前遍历到第i个数字,子序列最后一个数字为z时,最长子序列长度。其中0表示当前的数字在翻转的区间前面,1表示当前的数字在需要翻转的区间内,2表示当前的数字在翻转的区间后面。这样就可以很轻松的想到转移方程。
比较有难度的是第二问,即要输出翻转的是哪个区间。
考虑到,当状态从0->1,1->2时所选的是第几个数字是很容易维护的,因此可以维护2个数组,a数组表示从0->1时所选的第一个数字的下标,b数组表示从1->2时所选的第一个数字的下标,那么翻转的区间就是[a,b-1]
有个坑点是题目要求必须翻转,当不选择翻转的时候,可以选择翻转一个数字即可。
#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=a-1;i>=b;--i)
#define fuck(x) cout<<'['<<#x<<' '<<(x)<<']'
#define FIN freopen("in.txt","r",stdin);
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int mod = 1 << 30;
const int MX = 1e5 + 5;
int dp[2][10][3];
int a[2][10][3];
int b[2][10][3];
char s[MX];
void solve() {
int n;
scanf("%d", &n);
scanf("%s", s + 1);
int ans = 0, l = 0, r = 0;
rep(x, 0, 10) rep(y, 0, x + 1) {
memset(dp, 0, sizeof(dp));
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
rep(i, 1, n + 1) {
int now = s[i] - '0';
int cur = i & 1, pre = cur ^ 1;
rep(z, 0, y + 1) dp[cur][z][0] = dp[pre][z][0];
rep(z, y, x + 1) dp[cur][z][1] = dp[pre][z][1], a[cur][z][1] = a[pre][z][1];
rep(z, x, 10) dp[cur][z][2] = dp[pre][z][2], a[cur][z][2] = a[pre][z][2], b[cur][z][2] = b[pre][z][2];
if(now <= y) rep(z, 0, now + 1) {
if(dp[cur][now][0] < dp[pre][z][0] + 1) {
dp[cur][now][0] = dp[pre][z][0] + 1;
}
}
if(y <= now && now <= x) rep(z, 0, y + 1) {
if(dp[cur][now][1] < dp[pre][z][0] + 1) {
dp[cur][now][1] = dp[pre][z][0] + 1;
a[cur][now][1] = i;
}
}
if(y <= now && now <= x) rep(z, now, x + 1) {
if(dp[cur][now][1] < dp[pre][z][1] + 1) {
dp[cur][now][1] = dp[pre][z][1] + 1;
a[cur][now][1] = a[pre][z][1];
}
}
if(now >= x) rep(z, y, x + 1) {
if(dp[pre][z][1] && dp[cur][now][2] < dp[pre][z][1] + 1) {
dp[cur][now][2] = dp[pre][z][1] + 1;
a[cur][now][2] = a[pre][z][1];
b[cur][now][2] = i - 1;
}
}
if(now >= x) rep(z, x, now + 1) {
if(dp[pre][z][2] && dp[cur][now][2] < dp[pre][z][2] + 1) {
dp[cur][now][2] = dp[pre][z][2] + 1;
a[cur][now][2] = a[pre][z][2];
b[cur][now][2] = b[pre][z][2];
}
}
rep(z, 0, 10) rep(k, 0, 3) {
if(ans < dp[cur][z][k]) {
ans = dp[cur][z][k];
if(k == 0) l = r = 1;
else if(k == 1) l = a[cur][z][k], r = i;
else l = a[cur][z][k], r = b[cur][z][k];
}
}
}
}
printf("%d %d %d\n", ans, l, r);
}
int main() {
//freopen("in.txt", "r", stdin);
int T;
for(cin >> T; T; T--) solve();
return 0;
}