【题目】
LIS again
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 232 Accepted Submission(s): 74
Problem Description
A numeric sequence of ai is ordered if
a
1
<a
2
<…<a
N![]()
.
Let the subsequence of the given numeric sequence (a
1
,a
2
,…,a
N![]()
)
be any sequence (a
i
1![]()
,a
i
2![]()
,…,a
i
K![]()
![]()
),
where 1≤i
1
<i
2
<…<i
K
≤N
.
For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, eg. (1, 7), (3, 4, 8) and many others.
S[ i , j ] indicates ( a
i
,a
i+1
,a
i+2
,…,a
j![]()
)
.
Your program, when given the numeric sequence (a
1
,a
2
,…,a
N![]()
),
must find the number of pair ( i, j) which makes the length of the longest ordered subsequence of S[ i , j ] equals to the length of the longest ordered subsequence of (a
1
,a
2
,…,a
N![]()
).
S[ i , j ] indicates ( a
Your program, when given the numeric sequence (a
Input
Multi test cases (about 100), every case occupies two lines, the first line contain n, then second line contain n numbersa
1
,a
2
,…,a
N![]()
separated by exact one space.
Process to the end of file.
[Technical Specification]
1≤n≤100000![]()
0≤a
i
≤1000000000![]()
Process to the end of file.
[Technical Specification]
1≤n≤100000
0≤a
Output
For each case,.output the answer in a single line.
Sample Input
3 1 2 3 2 2 1
Sample Output
1 3
【分析】
题目要求的是等于最长上升序列的子串数量,只要求出以i结尾长度等于最长上升子序列的长度的最靠右的左下标,累加起来就是答案,不需要用线段树。具体看代码注释。
【AC CODE】 246ms
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <map>
//#include <unordered_map>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 100000+10;
int d[MAXN], p[MAXN];//p[i]表示以i结尾时最k靠右的左下标(下面简称左下标),也就是数量
int main()
{
#ifdef SHY
freopen("e:\\1.txt", "r", stdin);
#endif
int n;
while(~scanf("%d%*c", &n))
{
int a, len = 0;
LL ans = 0;
d[0] = -1;
repe(i,1,n)
{
scanf("%d%*c", &a);
int k = lower_bound(d,d+len,a)-d;
d[k++] = a;//k++变成1开始的下标
if(1 == k) p[k] = i;//k==1时长度为1,左下标则为i(新起点)
else p[k] = p[k-1];//否则p[k] = p[k-1]的值,因为是连续的,所以修改和增加长度都不会改变左下标
if(k > len)//长度增加时ans要重置为新长度的数量
ans = p[++len];
else ans += p[len];//长度不变时说明有新方案长度也能等于len,累加
}
printf("%I64d\n", ans);
}
return 0;
}