XDU1131 思維 dp優化

2022-03-16 16:46:48 字數 1459 閱讀 2782

題意

分析

乙個直觀的做法是,列舉前兩項,不斷檢查前一項,這需要維護乙個有序陣列並且帶下標(可以用乙個map>,將數字相同的數推倒乙個vector中,vector中存的就是相同的數的位置)

時間複雜度:o(n^2*(logn+logn))

這個做法不太行啊,兩個log,有點卡不過去

由於有很多重複的列舉,dp優化

dp[i][j]:以i,j為開始兩個的最大長度

轉移:顯然需要k且k>j的help,   a[k]=a[i]+a[j] (k>j)即可(二分即可)

另一種dp[i][j]:以i,j為結束兩個的最大長度

轉移:需要k且k

但這個狀態不太好找二分不好check

時間複雜度o(n^2*logn)

#include #include 

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define lson l,(l+r)/2,rt<<1

#define rson (l+r)/2+1,r,rt<<1|1

#define dbg(x) cout<

#define pb push_back

#define fi first

#define se second

#define ll long long

#define sz(x) (int)(x).size()

#define pll pair#define pii pair#define pq priority_queuevector

v;int dp[1010][1010

];ll a[

1010

];int

main());

}if(n==1

) sort(v.begin(),v.end());

pll res;

int cnt=0

;

for(int i=n-1;i>=1;i--));

if(it!=v.end() && it->fi==a[i]+a[j])

else

if(dp[i][j]>cnt || (dp[i][j]==cnt && (pll)

cnt=dp[i][j];}}

}printf(

"%d\n

",cnt);

printf(

"%lld %lld

",res.fi,res.se);

for(int i=2;i)

printf("\n

");}

return0;

}

view code

小D的劇場(思維dp)

時間限制 c c 1秒,其他語言2秒 空間限制 c c 131072k,其他語言262144k 64bit io format lld 若你摘得小的星星 你將得到小的幸福 若你摘得大的星星 你將得到大的財富 若兩者都能摘得 你將得到永遠的願望 摘星是罪孽的寬恕 摘星是夜晚的奇蹟 抓住它吧 你所期望的...

CodeForces 1060D(思維 貪心)

n個人圍成乙個圈吃飯,每個人都要求自己的左右兩邊至少有多少座椅,求最少的座椅數量 第一次做這種題,看了好久沒有思路,仔細想一想,每次挑選左右座椅最大的那個加起來,最後得出的就是最小座椅數量。因為是乙個圈,選擇大的那一邊,下一次選擇就會把另一邊給覆蓋 include using namespace s...

codeforces 1375D 模擬 思維

1375d 1900的題 題意 給你乙個n,然後是乙個陣列,其中的值為0 n,定義mex為陣列中0 n不存在的最小的那個,操作為可以將第i個數字為mex,使得這個陣列為不遞減的陣列,可以證明操作次數在2n次內一定能實現,問你操作次數是多少,並輸出相對應的索引,操作次數不要求是最優的。思路 看到在2n...