2012-03-19 69 views
5

tôi đang cố gắng để giải quyết những câu dưới đây:dãy dài nhất mà tăng đầu tiên sau đó giảm


Một chuỗi trong đó giá trị của các yếu tố giảm đầu tiên và sau đó tăng được gọi là V-Sequence. Trong một V-Sequence hợp lệ, cần có ít nhất một phần tử trong phần tử giảm dần và ít nhất một phần tử trong nhánh tăng. Ví dụ: "5 3 1 9 17 23" là một chuỗi V hợp lệ có hai phần tử trong nhánh giảm là 5 và 3 và 3 phần tử trong nhánh tăng là 9, 17 và 23. Nhưng không có chuỗi nào "6 4 2" hoặc "8 10 15" là V-Sequence vì "6 4 2" không có phần tử nào trong phần tăng lên trong khi "8 10 15" không có phần tử trong phần giảm.

Một chuỗi con của chuỗi được lấy bằng cách xóa 0 hoặc nhiều phần tử khác khỏi chuỗi. Ví dụ: định nghĩa "7", "2 10", "8 2 7 6", "8 2 7 10 6" v.v ... là các chuỗi con hợp lệ của "8 2 7 10 6"

Cho một dãy số N tìm chuỗi phụ dài nhất của nó, đó là một chuỗi V-Sequence.


Tôi hiện đang có một O (n^2) giải pháp trong đó đầu tiên tôi khởi tạo một mảng (m []) sao cho mỗi m [i] chứa các chuỗi tăng dài nhất bắt đầu từ 'i' trong mảng.

Tương tự, tôi khởi tạo một mảng khác (d []), sao cho mỗi d [i] chứa chuỗi giảm dài nhất ENDING tại điểm đó.

Cả hai hoạt động lấy O (n^2)

bây giờ tôi đi qua các mảng và chọn giá trị lớn nhất của m [i] + d [i] -1, như vậy mà điều kiện cần được thỏa mãn.

Điều tôi muốn biết là - Có giải pháp O (n lg n) không ?? Bởi vì giải pháp của tôi không chạy trong giới hạn thời gian yêu cầu. Cảm ơn bạn :)

Mã sản phẩm:

#include<cstdio> 
#include<algorithm> 

using namespace std; 



int m[ 200000 ]; 
int d[200000 ]; 
int n; 
int arr[200000 ]; 

void LIS() 
{ 
    m[ n-1 ] = 1; 

    int maxvPos = -1; 
    int maxv = -1; 

    for(int i=n-2; i>=0; i--) 
    { 
     maxv = -1; 
     for(int j=i+1; j<n; j++) 
     { 
      if((m[j]+1 > maxv) && (arr[i] < arr[j])) 
      { 
       maxv = m[j]+1; 
       maxvPos = j; 
      } 


     } 
     if(maxv>0) 
      { 
       m[i] = maxv; 
      } 

      else 
       m[i ] = 1; 
    } 

} 

void LDS() 
{ 
     d[0] = 1; 

    int maxv = -1; 
    int maxvPos = -1; 

    for(int i=1; i<n; i++) 
    { 
     maxv = -1; 
     for(int j=i-1; j>=0; j--) 
     { 
      if((d[j]+1 > maxv) && arr[j]>arr[i]) 
      { 
       maxv = d[j]+1; 
       maxvPos = j; 
      } 
     } 

     if(maxv>0) 
      d[i] = maxv; 

     else 
      d[i]=1; 
    } 

} 

int solve() 
{ 
    LIS(); 
    LDS(); 

    int maxv = 0; 
    int curr = 0; 

    for(int i=0; i<n; i++) 
    { 
     curr = d[i] + m[i] -1 ; 

     if((d[i]>0) && (m[i]>0)) 
     { 
      if(curr != 1) 
      maxv = max(curr, maxv); 
     } 

    } 

    return maxv; 

} 

/* static void printArr(int[] a) 
{ 
    for(int i : a) 
     System.out.print(i + " "); 

    System.out.println(); 
} */ 


int main() 
{ 
    scanf("%d", &n); 

    for(int i=0; i<n; i++) 
    { 
     scanf("%d", &arr[i]); 
    } 

    printf("%d\n", solve()); 
    return 0; 

} 
+1

Đó là từ một cuộc thi lập trình diễn ra tối qua. Bài gửi của tôi đã vượt quá thời gian cho 6 trong số 11 trường hợp kiểm tra. – arya

Trả lời

5

O(NlgK) thuật toán cho Longest Tăng vấn đề dãy, nơi K là chiều dài LIS. Bạn có thể kiểm tra Wikipedia để biết mô tả về thuật toán. LightOJ cũng có một hướng dẫn tốt đẹp (điều này có thể yêu cầu đăng nhập).

+0

Cảm ơn u :) Liên kết wikipedia không giúp được gì nhiều, nhưng liên kết thứ hai rất tốt! – arya

0

Chỉnh sửa: Ồ, câu trả lời này là sai. Tôi đã quên một phần về việc có thể xóa các phần tử để tạo ra các chuỗi phù hợp dài hơn. Tuy nhiên, để giải trí, đây là một giải pháp đối với trường hợp đơn giản mà bạn không nhận được để xóa các yếu tố:

tôi có thể nghĩ đến một O (n) giải pháp:

Đi bộ danh sách một lần.Duy trì một số biến:

  • đầu dài nhất v-sequence thấy
  • chiều dài dài nhất v-sequence thấy
  • đầu hiện tại v-chuỗi
  • quét vị trí hiện tại
  • quét nhà nước hiện hành (tăng dần hoặc giảm dần)

Khởi tạo cả hai con trỏ đầu tiên đến phần tử đầu tiên, dài nhất đến 0 và trạng thái quét để giảm dần.

  1. Đi bộ danh sách miễn là số đang giảm dần và ở trạng thái giảm dần.
  2. Khi gặp phải số lượng ngày càng tăng, hãy chuyển sang trạng thái tăng dần và tiếp tục đi bộ
  3. Khi số giảm tiếp theo được mã hóa, đây là phần cuối của chuỗi v.
  4. So sánh với chuỗi v-chuỗi dài nhất hiện tại và cập nhật nếu điều này dài hơn.
  5. Đặt lại bắt đầu hiện tại v-trình tự và quét nhà nước để giảm dần
  6. Walk the chuỗi tiếp theo
  7. Tại cuối mảng, trở về bắt đầu và chiều dài của chuỗi dài nhất.
+0

Câu trả lời yêu cầu một chuỗi không nhất thiết tiếp giáp. – arya

+0

Được chú ý và chỉnh sửa. – blueshift

+0

Tôi nghĩ bạn đã hiểu nhầm vấn đề. Các chuỗi phụ không cần phải liên tục. Ví dụ, đối với đầu vào "1 4 2 7 3", kết quả sẽ là 4 [1 4 7 3]. –

0

Đây là giải pháp O (n). Đã kiểm tra nó trên các ví dụ cơ bản.
Hãy cho tôi biết nếu nó có bất kỳ vấn đề gì hoặc nếu nó không hoạt động đối với bất kỳ trường hợp cụ thể nào.

Mã sản phẩm:

#include<stdio.h> 
int max(int a,int b) 
{ 
return (a >= b ? a : b); 
} 
int main() 
{ 
    int i,j,n; 
    scanf("%d",&n); 
    int A[200022]; 
    int dec[200022]={0}; 
    int V[200022]={0}; 
    int state[200022]={0}; 
    for(i=0;i<n;i++) 
    { 
     scanf("%d",&A[i]); 
    } 
    if(A[0] > A[1]) 
     state[0]=1; 
    for(i=1;i<n;i++) 
    { 
     j=i-1; 
      if(A[i] < A[j]) 
      {  
       dec[i]=max(dec[i],dec[j]+1); 
       V[i]=max(V[i],V[j]); 
       state[i]=1; 
      }  
      else if(A[i] == A[j]) 
      {  
       dec[i]=dec[j]; 
       V[i]=V[j]; 
       state[i]=state[j]; 
      } 
      else 
      { 
       if(state[j]==1) 
       { 
        dec[i]=dec[i]; 
        V[i]=max(V[i],dec[j]+1); 
        V[i]=max(V[i],V[j]+1); 
        state[i]=1; 
       } 
       else 
       { 
        dec[i]=dec[i]; 
        V[i]=max(V[i],V[j]); 
       } 
      } 

// printf("%d %d\n",dec[i],V[i]); 
} 
    if(V[n-1] == 0) 
     printf("0\n"); 
    else 
     printf("%d\n",V[n-1]+1); 
} 
0

Thi công mảng inc [i] nơi inc [i] cửa hàng tăng dài nhất dãy kết thúc với A [i]. Xây dựng mảng dec [i] trong đó dec [i] lưu trữ chuỗi dài nhất Giảm kết thúc bằng A [i].

sau đó tìm giá trị lớn nhất của (inc [i] + dec [i] - 1)

Các vấn đề liên quan