给定一个长度为N的数组arr[] ,任务是找到给定数组中严格递增的子序列的数量。
例子:
Input: arr[] = {1, 2, 3}
Output: 7
All increasing sub-sequences will be:
1) {1}
2) {2}
3) {3}
4) {1, 2}
5) {1, 3}
6) {2, 3}
7) {1, 2, 3}
Thus, answer = 7
Input: arr[] = {3, 2, 1}
Output: 3
方法:本文已经讨论了 O(N 2 ) 方法。在这里,将讨论使用段树数据结构的 O(NlogN) 时间的方法。
在上一篇文章中,使用的递推关系是:
dp[i] = 1 + summation(dp[j]), where i
由于整个子数组arr[i+1…n-1]正在为每个状态迭代,因此需要额外的 O(N) 时间来解决它。因此,复杂度为(N 2 )。
这个想法是为了避免为每个状态迭代 O(N) 额外循环并将其复杂性降低到 Log(N)。
假设:从每个索引“i”开始的严格递增子序列的数量是已知的,其中 i 大于数字“k”。
使用上述假设,可以在 log(N) 时间内找到从索引 ‘k’ 开始的增加子序列的数量。
因此,必须找到所有索引“i”大于“k”的总和。但问题是 arr[i] 必须大于 arr[k]。为了解决这个问题,可以做以下事情:
1.对于数组的每个元素,它的索引是在数组中找到的被排序的。示例 – {7, 8, 1, 9, 4} 这里,排名将是:
7 -> 3
8 -> 4
1 -> 1
9 -> 5
4 -> 2
2. 创建长度为“N”的段树来回答范围总和查询。
3. 为了在求解索引 ‘k’ 的同时回答查询,首先找到arr[k]的排名。假设等级是R 。然后,在段树中,找到从索引{R 到 N-1}的范围和。
4. 然后,segment-tree 点更新为segment-(R-1) 等于 1 + segtree-query(R, N-1) + segtree-query(R-1, R-1)
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define N 10000
// Segment tree array
int seg[3 * N];
// Function for point update in segment tree
int update(int in, int l, int r, int up_in, int val)
{
// Base case
if (r < up_in || l > up_in)
return seg[in];
// If l==r==up
if (l == up_in and r == up_in)
return seg[in] = val;
// Mid element
int m = (l + r) / 2;
// Updating the segment tree
return seg[in] = update(2 * in + 1, l, m, up_in, val)
+ update(2 * in + 2, m + 1, r, up_in, val);
}
// Function for the range sum-query
int query(int in, int l, int r, int l1, int r1)
{
// Base case
if (l > r)
return 0;
if (r < l1 || l > r1)
return 0;
if (l1 <= l and r <= r1)
return seg[in];
// Mid element
int m = (l + r) / 2;
// Calling for the left and the right subtree
return query(2 * in + 1, l, m, l1, r1)
+ query(2 * in + 2, m + 1, r, l1, r1);
}
// Function to return the count
int findCnt(int* arr, int n)
{
// Copying array arr to sort it
int brr[n];
for (int i = 0; i < n; i++)
brr[i] = arr[i];
// Sorting array brr
sort(brr, brr + n);
// Map to store the rank of each element
map r;
for (int i = 0; i < n; i++)
r[brr[i]] = i + 1;
// dp array
int dp[n] = { 0 };
// To store the final answer
int ans = 0;
// Updating the dp array
for (int i = n - 1; i >= 0; i--) {
// Rank of the element
int rank = r[arr[i]];
// Solving the dp-states using segment tree
dp[i] = 1 + query(0, 0, n - 1, rank, n - 1);
// Updating the final answer
ans += dp[i];
// Updating the segment tree
update(0, 0, n - 1, rank - 1,
dp[i] + query(0, 0, n - 1, rank - 1, rank - 1));
}
// Returning the final answer
return ans;
}
// Driver code
int main()
{
int arr[] = { 1, 2, 10, 9 };
int n = sizeof(arr) / sizeof(int);
cout << findCnt(arr, n);
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG
{
static final int N = 10000;
// Segment tree array
static int[] seg = new int[3 * N];
// Function for point update in segment tree
static int update(int in, int l, int r, int up_in, int val)
{
// Base case
if (r < up_in || l > up_in)
return seg[in];
// If l==r==up
if (l == up_in && r == up_in)
return seg[in] = val;
// Mid element
int m = (l + r) / 2;
// Updating the segment tree
return seg[in] = update(2 * in + 1, l, m, up_in, val) +
update(2 * in + 2, m + 1, r, up_in, val);
}
// Function for the range sum-query
static int query(int in, int l, int r, int l1, int r1)
{
// Base case
if (l > r)
return 0;
if (r < l1 || l > r1)
return 0;
if (l1 <= l && r <= r1)
return seg[in];
// Mid element
int m = (l + r) / 2;
// Calling for the left and the right subtree
return query(2 * in + 1, l, m, l1, r1) +
query(2 * in + 2, m + 1, r, l1, r1);
}
// Function to return the count
static int findCnt(int[] arr, int n)
{
// Copying array arr to sort it
int[] brr = new int[n];
for (int i = 0; i < n; i++)
brr[i] = arr[i];
// Sorting array brr
Arrays.sort(brr);
// Map to store the rank of each element
HashMap r = new HashMap();
for (int i = 0; i < n; i++)
r.put(brr[i], i + 1);
// dp array
int dp[] = new int[n];
// To store the final answer
int ans = 0;
// Updating the dp array
for (int i = n - 1; i >= 0; i--)
{
// Rank of the element
int rank = r.get(arr[i]);
// Solving the dp-states using segment tree
dp[i] = 1 + query(0, 0, n - 1, rank, n - 1);
// Updating the final answer
ans += dp[i];
// Updating the segment tree
update(0, 0, n - 1, rank - 1, dp[i] +
query(0, 0, n - 1, rank - 1, rank - 1));
}
// Returning the final answer
return ans;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 2, 10, 9 };
int n = arr.length;
System.out.print(findCnt(arr, n));
}
}
// This code is contributed by PrinciRaj1992
Python3
# Python3 implementation of the approach
N = 10000
# Segment tree array
seg = [0] * (3 * N)
# Function for point update in segment tree
def update(In, l, r, up_In, val):
# Base case
if (r < up_In or l > up_In):
return seg[In]
# If l==r==up
if (l == up_In and r == up_In):
seg[In] = val
return val
# Mid element
m = (l + r) // 2
# Updating the segment tree
seg[In] = update(2 * In + 1, l, m, up_In, val) + update(2 * In + 2, m + 1, r, up_In, val)
return seg[In]
# Function for the range sum-query
def query(In, l, r, l1, r1):
# Base case
if (l > r):
return 0
if (r < l1 or l > r1):
return 0
if (l1 <= l and r <= r1):
return seg[In]
# Mid element
m = (l + r) // 2
# CallIng for the left and the right subtree
return query(2 * In + 1, l, m, l1, r1)+ query(2 * In + 2, m + 1, r, l1, r1)
# Function to return the count
def fIndCnt(arr, n):
# Copying array arr to sort it
brr = [0] * n
for i in range(n):
brr[i] = arr[i]
# Sorting array brr
brr = sorted(brr)
# Map to store the rank of each element
r = dict()
for i in range(n):
r[brr[i]] = i + 1
# dp array
dp = [0] * n
# To store the final answer
ans = 0
# Updating the dp array
for i in range(n - 1, -1, -1):
# Rank of the element
rank = r[arr[i]]
# Solving the dp-states using segment tree
dp[i] = 1 + query(0, 0, n - 1, rank, n - 1)
# UpdatIng the final answer
ans += dp[i]
# Updating the segment tree
update(0, 0, n - 1, rank - 1,dp[i] + query(0, 0, n - 1, rank - 1, rank - 1))
# Returning the final answer
return ans
# Driver code
arr = [1, 2, 10, 9]
n = len(arr)
print(fIndCnt(arr, n))
# This code is contributed by mohit kumar 29
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG
{
static readonly int N = 10000;
// Segment tree array
static int[] seg = new int[3 * N];
// Function for point update In segment tree
static int update(int In, int l, int r,
int up_in, int val)
{
// Base case
if (r < up_in || l > up_in)
return seg[In];
// If l==r==up
if (l == up_in && r == up_in)
return seg[In] = val;
// Mid element
int m = (l + r) / 2;
// Updating the segment tree
return seg[In] = update(2 * In + 1, l, m, up_in, val) +
update(2 * In + 2, m + 1, r, up_in, val);
}
// Function for the range sum-query
static int query(int In, int l, int r, int l1, int r1)
{
// Base case
if (l > r)
return 0;
if (r < l1 || l > r1)
return 0;
if (l1 <= l && r <= r1)
return seg[In];
// Mid element
int m = (l + r) / 2;
// Calling for the left and the right subtree
return query(2 * In + 1, l, m, l1, r1) +
query(2 * In + 2, m + 1, r, l1, r1);
}
// Function to return the count
static int findCnt(int[] arr, int n)
{
// Copying array arr to sort it
int[] brr = new int[n];
for (int i = 0; i < n; i++)
brr[i] = arr[i];
// Sorting array brr
Array.Sort(brr);
// Map to store the rank of each element
Dictionary r = new Dictionary();
for (int i = 0; i < n; i++)
r.Add(brr[i], i + 1);
// dp array
int []dp = new int[n];
// To store the readonly answer
int ans = 0;
// Updating the dp array
for (int i = n - 1; i >= 0; i--)
{
// Rank of the element
int rank = r[arr[i]];
// Solving the dp-states using segment tree
dp[i] = 1 + query(0, 0, n - 1, rank, n - 1);
// Updating the readonly answer
ans += dp[i];
// Updating the segment tree
update(0, 0, n - 1, rank - 1, dp[i] +
query(0, 0, n - 1, rank - 1, rank - 1));
}
// Returning the readonly answer
return ans;
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 1, 2, 10, 9 };
int n = arr.Length;
Console.Write(findCnt(arr, n));
}
}
// This code is contributed by PrinciRaj1992
Javascript
11
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。