標籤:dp,線段樹,資料結構
清晰版題目描述
小強拿到乙個3×n的陣列,要在每一列選乙個數(或者不選),滿足以下條件:
1.如果在第一行選,那它必須大於等於上乙個數
2.如果在第二行選,那麼必須小於等於上乙個數
3.如果在第三行選,對於連續的一段在第三行選的數,必須滿足方向相同(都小於等於上乙個數或者都大於等於上乙個數)
輸入輸出格式
輸入格式:
輸入包含4行。
第一行乙個數n,表示數列長度。
第2、3、4行,每行n個整數,分別表示三個數列。
輸出格式:
輸出僅包含乙個整數,即最長波動數列的長度。
輸入輸出樣例
輸入樣例#1:複製 6
1 2 3 6 5 4
5 4 3 7 8 9
1 2 3 6 5 4
輸出樣例#1:複製 6
說明
對於20%的資料,n <= 10, m <= 1000
對於60%的資料,n <=1000, m <= 1000
對於100%的資料, n <=100000, m <= 1000000000
其中m = max|a[i]|
樣例解釋:
取第三行1 2 3(增),然後取第1行6(增),然後取第三行5 4(減),長度為6。
分析:dp裸題,設f[i][1/2/3/4]分別表示取前i列數中以第1/2/3/4行結尾的最長波動數列長度
f[i][1]=max(f[j][1/2/3/4]+1) j
剩下三行的轉移同理,這種做法時間複雜度為o(n^2)
滿分的做法可以直接用線段樹維護
code
#include#include#include#include#include#include#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define mem(x,num) memset(x,num,sizeof x)
#define ll long long
using namespace std;
inline ll read()
while(ch>='0'&&ch<='9')
return x*f;
}const int maxn=1e5+6;
int n,cnt=0,ans=0;
int a[maxn],b[maxn],c[maxn],num[maxn<<4],f[maxn][5],tree[maxn<<4][5];
void insert(int id,int rt,int l,int r,int pos,int v)
int mid=(l+r)>>1;
if(pos<=mid)insert(id,rt<<1,l,mid,pos,v);
else insert(id,rt<<1|1,mid+1,r,pos,v);
tree[rt][id]=max(tree[rt<<1][id],tree[rt<<1|1][id]);
}int query(int id,int rt,int l,int r,int l,int r)
int main()
rep(i,1,n)
rep(j,1,4)ans=max(ans,f[i][j]);
printf("%d\n",ans);
return 0;
}
洛谷P3927 一道中檔題
題目 洛谷月賽,qbxt考試的時候划水去做了t1 當時沒看見多組資料悲慘的wa了 然而題目現在改了?翻提交記錄時驚喜的發現當年的0分變成了70?70分是被int坑了 答案是在longlong範圍裡的 思路 k進製下末尾0的個數即為該數最大可整除的k的次方數 將k質因數分解,統計k的每個質因子在n 中...
一道簡單的題
阿里巴巴的一道面試題 25.給定乙個整數陣列和乙個整數,返回兩個陣列的索引,這兩個索引指向的數字的加和等於指定的整數。需要最優的演算法,分析演算法的空間和時間複雜度。include include using namespace std struct stwoindex 初始化,同時等於0,說明不存...
一道簡單DP題
首先,一看就應該知道這是一道dp題。原因在於其當前結果都依賴於前面計算得到的子結果。區分分治和dp的關鍵條件就在於演算法執行中間階段的計算結果是否依賴於其子問題的結果,若依賴則為dp,否則為分治。dp題的關鍵在於找出狀態轉移方程和初始條件 或者稱為邊界值 找出狀態轉移方程的關鍵又在於找對乙個狀態函式...