CodeForces - 1497D Genius(dp)
題目鏈接:點(diǎn)擊查看
題目大意:給出 nnn 個問題,每個問題有如下屬性:
初始時 ci=2ic_i=2^ici?=2i,初始時 IQ=0IQ=0IQ=0 ,假設(shè) lastlastlast 是最后一個回答的問題,則需要滿足 ∣ci?clast∣>IQ|c_i-c_{last}|>IQ∣ci??clast?∣>IQ 才可以回答問題 iii,且回答之后會發(fā)生的變化:
可以以任意順序回答任意問題任意次,問最大可以獲得的獎勵值是多少
題目分析:動態(tài)規(guī)劃問題,先不考慮題目限制,一開始設(shè)計的狀態(tài)是 dpi,jdp_{i,j}dpi,j? ,指倒數(shù)第二次回答的是問題 iii ,最后一次回答的是問題 jjj 的最大貢獻(xiàn),正確性顯然,但是轉(zhuǎn)移的方程好像有點(diǎn)爆
不過仔細(xì)觀察狀態(tài)之間的轉(zhuǎn)移,若 dpi,jdp_{i,j}dpi,j? 想要轉(zhuǎn)移到 dpj,kdp_{j,k}dpj,k?,當(dāng)且僅當(dāng) ∣ck?ci∣>∣ci?cj∣|c_k-c_i|>|c_i-c_j|∣ck??ci?∣>∣ci??cj?∣ 才行
將模型放到圖論上去,就變成了:有 nnn 個點(diǎn),任意兩點(diǎn)之間都可以建邊,且邊權(quán)為 ∣ci?cj∣|c_i-c_j|∣ci??cj?∣ 的一個無向圖,那么我們可以在無向圖上從小邊權(quán)向大邊權(quán)進(jìn)行迭代,這樣復(fù)雜度就下來了
簡單來說就是設(shè)計 dpidp_idpi? 為最后一個回答的問題是 iii 的最大貢獻(xiàn),當(dāng)?shù)?(i,j)(i,j)(i,j) 這條邊時, 狀態(tài) iii 可以由狀態(tài) jjj 更新,同時狀態(tài) jjj 也有可能被狀態(tài) iii 更新(因?yàn)槭菬o向圖),所以轉(zhuǎn)移方程如下:設(shè) val=∣si?sj∣val=|s_i-s_j|val=∣si??sj?∣
- dpi=max(dpi,dpj+val)dp_i=max(dp_i,dp_j+val)dpi?=max(dpi?,dpj?+val)
- dpj=max(dpj,dpi+val)dp_j=max(dp_j,dp_i+val)dpj?=max(dpj?,dpi?+val)
到此為止,我們還需要解決兩個問題:
關(guān)于第一點(diǎn)比較好論述,因?yàn)樗械倪厵?quán)都是諸如 ∣2i?2j∣|2^i-2^j|∣2i?2j∣ 的形式,將其轉(zhuǎn)換為二進(jìn)制后不難發(fā)現(xiàn),這個值在區(qū)間 [i,j?1][i,j-1][i,j?1] 的位置都是 111,其他位置都是 000,所以對于任意一對互不相同的 (i,j)(i,j)(i,j) 二元對來說,其權(quán)值都是互不相同的
關(guān)于第二點(diǎn),因?yàn)轭}目內(nèi)存的限制,使得我們沒辦法將所有的邊都存下來然后排序,但是,假如我們可以將邊存下來然后排序的話又能怎樣?二進(jìn)制遞增的速度非常快,以至于當(dāng) nnn 較大的時候,數(shù)值根本存不下,手玩一下找一下規(guī)律,不難發(fā)現(xiàn)二元對 (i,j)(i,j)(i,j) 權(quán)值的大小(假設(shè) i<ji<ji<j),由 jjj 主導(dǎo),當(dāng) jjj 相同的時候,權(quán)值大小與 iii 呈負(fù)相關(guān)的關(guān)系
所以在按照權(quán)值大小枚舉所有邊的時候,可以按照:
按照上述順序去枚舉所有的二元對 (i,j)(i,j)(i,j) ,就可以滿足枚舉的邊權(quán)是從小到大的了
代碼:
// Problem: D. Genius // Contest: Codeforces - Codeforces Round #708 (Div. 2) // URL: https://codeforces.com/contest/1497/problem/D // Memory Limit: 32 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=5e3+100; LL dp[N],tag[N],s[N]; int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--) {memset(dp,0,sizeof(dp));int n;read(n);for(int i=1;i<=n;i++) {read(tag[i]);}for(int i=1;i<=n;i++) {read(s[i]);}for(int j=2;j<=n;j++) {for(int i=j-1;i>=1;i--) {if(tag[i]==tag[j]) {continue;}LL dpi=dp[i],dpj=dp[j],val=abs(s[i]-s[j]);dp[i]=max(dp[i],dpj+val);dp[j]=max(dp[j],dpi+val);}}cout<<*max_element(dp,dp+n+1)<<endl;}return 0; } 超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的CodeForces - 1497D Genius(dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1484F U
- 下一篇: CodeForces - 1501C G