日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[AtCoder-ARC073F]Many Moves

發(fā)布時間:2025/3/8 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [AtCoder-ARC073F]Many Moves 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目大意:
  有一排n個格子和2枚硬幣。
  現(xiàn)在有q次任務(wù),每一次要你把其中一枚硬幣移到x的位置上,移動1格的代價是1。
  兩枚硬幣不能同時移動,任務(wù)必須按次序完成。
  現(xiàn)在告訴你兩枚硬幣初始狀態(tài)所在的位置a和b,問完成所有任務(wù)的最小代價。

思路:
  很容易想到一個O(qn)的DP。
  由于完成任務(wù)的次序確定,每個任務(wù)的位置也確定,我們可以用f[i][j]表示完成第i個任務(wù)后,一個硬幣在x[i],一個硬幣在j的最小代價。
  轉(zhuǎn)移方程為f[i][j]=min{f[i-1][j]+|x[i]-x[i-1]|},f[i][a[i-1]]=min{f[i-1][j]+|x[i]-j|}。
  然而這樣還是會TLE,在AtCoder上只過了14/34的測試數(shù)據(jù)。
  不難發(fā)現(xiàn),在狀態(tài)轉(zhuǎn)移方程中,如果我們能去掉絕對值,里面的東西就能用線段樹維護(hù)。
  而絕對值的取值只與硬幣的左右位置關(guān)系有關(guān)。
  因此我們可以建2棵線段樹,一棵表示被轉(zhuǎn)移的狀態(tài)在目標(biāo)狀態(tài)左邊,一棵表示在右邊。
  左線段樹中每個葉子結(jié)點x[i-1]維護(hù)f[i-1][j]-x[i-1]的值,右線段樹每個葉子結(jié)點x[i-1]維護(hù)f[i-1][j]+x[i-1]的值。
  看了一下榜,發(fā)現(xiàn)排在前面的基本上都是用樹狀數(shù)組做的。
  然而用樹狀數(shù)組維護(hù)區(qū)間最值難道不是O(log^2 n)的嗎?
  事實上我們可以發(fā)現(xiàn)線段樹上維護(hù)的東西只會越來越小,這樣我們可以直接在樹狀數(shù)組上修改,不用考慮原來的最小值沒了怎么辦。
  然后我又在樹狀數(shù)組里面加了一個剪枝。
  這樣隨隨便便就能拿Rank1。

1 #include<cstdio> 2 #include<cctype> 3 #include<cstdlib> 4 #include<algorithm> 5 typedef signed long long int int64; 6 inline unsigned getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register unsigned x=ch^'0'; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 11 return x; 12 } 13 inline int64 min(const int64 &a,const int64 &b) { 14 return a<b?a:b; 15 } 16 const int64 inf=0x7ffffffffffffff; 17 const int N=200001; 18 int n; 19 class FenwickTree { 20 private: 21 int64 val[N]; 22 int lowbit(const int &x) const { 23 return x&-x; 24 } 25 public: 26 FenwickTree() { 27 std::fill(&val[0],&val[N],inf); 28 } 29 void modify(int p,const int64 &x) { 30 while(p<=n) { 31 if(x<val[p]) { 32 val[p]=x; 33 } else { 34 return; 35 } 36 p+=lowbit(p); 37 } 38 } 39 int64 query(int p) const { 40 int64 ret=inf; 41 while(p) { 42 ret=min(ret,val[p]); 43 p-=lowbit(p); 44 } 45 return ret; 46 } 47 }; 48 FenwickTree ta; 49 class RevFenwickTree { 50 private: 51 int64 val[N]; 52 int lowbit(const int &x) const { 53 return x&-x; 54 } 55 public: 56 RevFenwickTree() { 57 std::fill(&val[0],&val[N],inf); 58 } 59 void modify(int p,const int64 &x) { 60 while(p) { 61 if(x<val[p]) { 62 val[p]=x; 63 } else { 64 return; 65 } 66 p-=lowbit(p); 67 } 68 } 69 int64 query(int p) const { 70 int64 ret=inf; 71 while(p<=n) { 72 ret=min(ret,val[p]); 73 p+=lowbit(p); 74 } 75 return ret; 76 } 77 }; 78 RevFenwickTree tb; 79 int64 f[N]; 80 inline void modify(const int &p,const int64 x) { 81 if(x<f[p]) { 82 f[p]=x; 83 ta.modify(p,x-p); 84 tb.modify(p,x+p); 85 } 86 } 87 int main() { 88 n=getint(); 89 int q=getint(),a=getint(),b=getint(); 90 std::fill(&f[0],&f[N],inf); 91 modify(a,0); 92 int64 sum=0; 93 while(q--) { 94 a=b; 95 b=getint(); 96 sum+=abs(a-b); 97 int64 t1=ta.query(b)+b,t2=tb.query(b)-b; 98 modify(a,min(t1,t2)-abs(a-b)); 99 } 100 int64 tmp=inf; 101 for(register int i=1;i<=n;i++) { 102 tmp=min(tmp,f[i]); 103 } 104 printf("%lld\n",tmp+sum); 105 return 0; 106 }

原來的O(n^2)DP程序:

1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 #include<cstdlib> 5 inline unsigned getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register unsigned x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 inline unsigned min(const unsigned &a,const unsigned &b) { 13 return a<b?a:b; 14 } 15 const unsigned N=200000; 16 unsigned long long f[2][N]; 17 unsigned a[2]; 18 int main() { 19 unsigned n=getint(),q=getint(); 20 memset(f[0],0xff,n<<3); 21 a[0]=getint()-1,f[0][getint()-1]=0; 22 for(register unsigned i=1;i<=q;i++) { 23 a[i&1]=getint()-1; 24 memset(f[i&1],0xff,n<<3); 25 for(register unsigned j=0;j<n;j++) { 26 if(!~f[~i&1][j]) continue; 27 f[i&1][j]=min(f[i&1][j],f[~i&1][j]+abs(a[i&1]-a[~i&1])); 28 f[i&1][a[~i&1]]=min(f[i&1][a[~i&1]],f[~i&1][j]+abs(a[i&1]-j)); 29 } 30 } 31 unsigned long long ans=~0; 32 for(register unsigned i=0;i<n;i++) { 33 ans=min(ans,f[q&1][i]); 34 } 35 printf("%llu\n",ans); 36 return 0; 37 } View Code

?

轉(zhuǎn)載于:https://www.cnblogs.com/skylee03/p/7609824.html

總結(jié)

以上是生活随笔為你收集整理的[AtCoder-ARC073F]Many Moves的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。