给定一个从1到N的大小N的排列。找到具有第一个和最后一个元素大于所有其他子序列元素的性质的最长子序列的长度。
例子:
Input : N = 6
4 2 6 5 3 1
Output : 3
The subsequence that has the longest size is [4, 2, 3] or [4, 2, 6] or [4, 2, 5]. No other subsequence holds the above property with first and last element greater than all remaining subsequence elements.
Input : N = 5
5 4 1 2 3
Output : 4
The longest subsequence is [5, 1, 2, 3] or [4, 1, 2, 3]. With 5 and 3 greater than all other subsequence elements i.e 1 and 2.
方法:
想法是使用Fenwick树数据结构,从排列中的最高值开始迭代到最低值。对于每次迭代,仅当可以将左指针移至更多左侧,将右指针移至更多右侧时,才将左指针或右指针移至当前元素。
如果左索引为L,右索引为R,则介于[L + 1,R-1]之间的元素。对于此特定迭代i,使用fenwick树计算小于min(arr [L],arr [R])的元素数。
存储类型为{left + 1,right-1,val,index}的每个查询,其中left和right是当前的左右指针,而val是arr [L]和arr [R]的最小值,idx是该索引该特定查询。
- 以升序对数组进行排序。
- 根据val排序查询,即min(arr [L],arr [R])升序,将Fenwick数组初始化为0。
- 从第一个查询开始,遍历数组,直到数组中的值小于等于val。对于每个此类元素,将Fenwick树更新为等于1的值。
- 查询范围为l到r的Fenwick数组。
- 打印所有查询结果的最大值。
下面是上述方法的实现:
CPP
// C++ implementation of the above approach
#include
using namespace std;
struct Query {
int l, r, x, index;
};
struct Arrays {
int val, index;
};
// Comparison functions
bool cmp1(Query q1, Query q2)
{
return q1.x < q2.x;
}
bool cmp2(Arrays x, Arrays y)
{
return x.val < y.val;
}
// Function to update the value in Fenwick tree
void update(int* Fenwick, int index, int val, int n)
{
while (index <= n) {
Fenwick[index] += val;
index += index & (-index);
}
}
// Function to return the query result
int query(int* Fenwick, int index, int n)
{
int sum = 0;
while (index > 0) {
sum = sum + Fenwick[index];
index -= index & (-index);
}
return sum;
}
// Function to return the length of subsequence
int maxLength(int n, vector& v)
{
int where[n + 2];
memset(where, 0, sizeof where);
Arrays arr[n];
// Store the value in struct Array
for (int i = 1; i <= n; ++i) {
v[i - 1] = v[i - 1] - 1;
int x = v[i - 1];
where[x] = i - 1;
arr[i - 1].val = x;
arr[i - 1].index = i - 1;
}
// If less than 2 elements are
// present return that element.
if (n <= 2) {
cout << n << endl;
return 0;
}
// Set the left and right pointers to extreme
int left = n, right = 0, mx = 0;
Query queries[4 * n];
int j = 0;
for (int i = n - 1; i >= 0; --i) {
// Calculate left and right pointer index.
left = min(left, where[i]);
right = max(right, where[i]);
int diff = right - left;
if (diff == 0 || diff == 1) {
continue;
}
int val1 = v[left];
int val2 = v[right];
int minn = min(val1, val2);
// Store the queries from [L+1, R-1].
queries[j].l = left + 1;
queries[j].r = right - 1;
queries[j].x = minn;
queries[j].index = j;
++j;
}
int Fenwick[n + 1];
memset(Fenwick, 0, sizeof Fenwick);
int q = j - 1;
// Sort array and queries for fenwick updates
sort(arr, arr + n + 1, cmp2);
sort(queries, queries + q + 1, cmp1);
int curr = 0;
int ans[q];
memset(ans, 0, sizeof ans);
// For each query calculate maxx for
// the answer and store it in ans array.
for (int i = 0; i <= q; ++i) {
while (arr[curr].val <= queries[i].x and curr < n) {
update(Fenwick, arr[curr].index + 1, 1, n);
curr++;
}
ans[queries[i].index] =
query(Fenwick, queries[i].r + 1, n)
- query(Fenwick, queries[i].l, n);
}
for (int i = 0; i <= q; ++i) {
mx = max(mx, ans[i]);
}
// Mx will be mx + 2 as while calculating
// mx, we excluded element
// at index left and right
mx = mx + 2;
return mx;
}
// Driver Code
int main()
{
int n = 6;
vector v = { 4, 2, 6, 5, 3, 1 };
cout << maxLength(n, v) << endl;
return 0;
}
Python3
# Python implementation of the above approach
from typing import List
class Query:
def __init__(self) -> None:
self.l = 0
self.r = 0
self.x = 0
self.index = 0
class Arrays:
def __init__(self) -> None:
self.val = 0
self.index = 0
# Function to update the value in Fenwick tree
def update(Fenwick: List[int], index: int, val: int, n: int) -> None:
while (index <= n):
Fenwick[index] += val
index += index & (-index)
# Function to return the query result
def query(Fenwick: List[int], index: int, n: int) -> int:
summ = 0
while (index > 0):
summ = summ + Fenwick[index]
index -= index & (-index)
return summ
# Function to return the length of subsequence
def maxLength(n: int, v: List[int]) -> int:
where = [0 for _ in range(n + 2)]
arr = [Arrays() for _ in range(n)]
# Store the value in struct Array
for i in range(1, n + 1):
v[i - 1] = v[i - 1] - 1
x = v[i - 1]
where[x] = i - 1
arr[i - 1].val = x
arr[i - 1].index = i - 1
# If less than 2 elements are
# present return that element.
if (n <= 2):
print(n)
return 0
# Set the left and right pointers to extreme
left = n
right = 0
mx = 0
queries = [Query() for _ in range(4 * n)]
j = 0
for i in range(n - 1, -1, -1):
# Calculate left and right pointer index.
left = min(left, where[i])
right = max(right, where[i])
diff = right - left
if (diff == 0 or diff == 1):
continue
val1 = v[left]
val2 = v[right]
minn = min(val1, val2)
# Store the queries from [L+1, R-1].
queries[j].l = left + 1
queries[j].r = right - 1
queries[j].x = minn
queries[j].index = j
j += 1
Fenwick = [0 for _ in range(n + 1)]
q = j - 1
# Sort array and queries for fenwick updates
arr[:n + 1].sort(key=lambda x: x.val)
queries[:q + 1].sort(key=lambda val: val.x)
curr = 0
ans = [0 for _ in range(q + 1)]
# For each query calculate maxx for
# the answer and store it in ans array.
for i in range(q + 1):
while (arr[curr].val <= queries[i].x and curr < n):
update(Fenwick, arr[curr].index + 1, 1, n)
curr += 1
# if queries[i].index < q:
ans[queries[i].index] = query(Fenwick, queries[i].r + 1, n) - query(
Fenwick, queries[i].l, n)
for i in range(q + 1):
mx = max(mx, ans[i])
# Mx will be mx + 2 as while calculating
# mx, we excluded element
# at index left and right
mx = mx + 2
return mx
# Driver Code
if __name__ == "__main__":
n = 6
v = [4, 2, 6, 5, 3, 1]
print(maxLength(n, v))
# This code is contributed by sanjeev2552
3