洛谷P1912:诗人小G(二分栈、决策单调性)
生活随笔
收集整理的這篇文章主要介紹了
洛谷P1912:诗人小G(二分栈、决策单调性)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
二分棧,就是通過二分維護的棧
(逃)
解析
本題的決策單調性可以說是顯然
但是本題是同維度(其實只有一維)自左向右轉移,分治的寫法是不能奏效的
所以我們使用決策點調性的另一種實現方法:二分棧
具體來說,維護[1,n]各自的最優轉移點
一開始的轉移點全是0,把三元組(0,1,n)(0,1,n)(0,1,n)push入棧,分別表示轉移點和左右端點
然后從1掃到n
掃到i的時候,利用i當前的最優決策點進行轉移
然后嘗試更新后面的最優決策點
不斷取出棧頂,如果棧頂區間在 l 的位置還是不如當前的轉移,顯然這個區間沒有用了,彈出棧頂
然后對于無法使之彈出的區間,二分出其與自己在何時會發生最優轉移的變化,如果這個變化的位置pl<=n,把(i,pl,n)(i,pl,n)(i,pl,n)入棧,并把之前的棧頂區間右端點改為pl-1
然后就解決啦!
注意事項
至少是我易錯的
二分的時候當calc相等的時候不能草率!可能是都返回了inf,所以要按照這個時候那個絕對值的正負分類討論
while(st<ed){int mid=(st+ed)>>1;ll a=calc(j,mid),b=calc(i,mid);if(a<b||(a==b&&sum[mid]-sum[i]-l-1>0)) ed=mid;else st=mid+1; }代碼
#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline #define debug(a) fprintf(stderr,a) const int N=1e5+100; const int M=3e6+100; const int mod=998244353; inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } int n,p,l; ll f[N],sum[N]; ll ksm(ll x,ll k){if(x<0) x=-x;ll res=1;while(k){if(k&1) res*=x;x=x*x;k>>=1;}return res; } inline ll calc(int i,int j){//printf(" calc:%d %d jd=%lld>%lf\n",i,j,abs(sum[j]-sum[i]-l-1),(1.0*log(1e18-f[i])/log(p)));if(abs(sum[j]-sum[i]-l-1)&&(f[i]>1e18||p>1.0*log(2e18-f[i])/log(abs(sum[j]-sum[i]-l-1)))) return 2e18+1;else return f[i]+ksm(sum[j]-sum[i]-l-1,p); } #define pr pair<int,int> #define mkp make_pair pr q[N];//id st int st,ed; char s[N][33]; int pre[N]; int find(int i,int j){int st=j+1,ed=n+1;while(st<ed){int mid=(st+ed)>>1;ll a=calc(j,mid),b=calc(i,mid);if(a<b||(a==b&&sum[mid]-sum[i]-l-1>0)) ed=mid;else st=mid+1;}//printf("find:i=%d j=%d st=%d\n",i,j,st);return st; } int a[N],b[N],tot; int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifint T=read();while(T--){n=read();l=read();p=read();for(int i=1;i<=n;i++){scanf(" %s",s[i]+1);sum[i]=sum[i-1]+strlen(s[i]+1)+1;//printf("i=%d sum=%d\n",i,sum[i]);}st=ed=1;q[1]=mkp(0,1);int flag=0;for(int i=1;i<=n;i++){while(st<ed&&q[st+1].second<=i) st++;int now=q[st].first;pre[i]=now;f[i]=calc(now,i);//printf("i=%d now=%d f=%lld\n",i,now,f[i]);while(st<=ed){int pl=find(q[ed].first,i);if(pl<=q[ed].second) ed--;else{if(pl<=n) q[++ed]=mkp(i,pl);break;}}if(st>ed) q[++ed]=mkp(i,i+1);}//debug("ok");if(f[n]>1e18) printf("Too hard to arrange\n");else{printf("%lld\n",f[n]);tot=0;int pl=n;while(pl){b[++tot]=pl;pl=pre[pl];a[tot]=pl+1;}for(int i=tot;i>=1;i--){for(int j=a[i];j<=b[i];j++){printf("%s",s[j]+1);if(j!=b[i]) putchar(' ');}printf("\n");}}printf("--------------------\n");}return 0; } /* 3 1 3 1 33 2 1 1 2 3 1 3 */總結
以上是生活随笔為你收集整理的洛谷P1912:诗人小G(二分栈、决策单调性)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么往网页里加音乐(怎么往网页里加音乐文
- 下一篇: 10.27模拟 总结