2021牛客暑期多校训练营2 G.League of Legends(转化+单调队列)
生活随笔
收集整理的這篇文章主要介紹了
2021牛客暑期多校训练营2 G.League of Legends(转化+单调队列)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
G.League of Legends
Zechariah_2001題解
對于可以包含其他區間的大區間,要使得答案最優無非就是兩種分組方式:單獨一組或者與被包含的區間一組。單獨一組那么貢獻就是區間長度;如果說與被包含的區間一組,對答案貢獻為0,因為根據題意,如果有多個區間,添加區間實際上是添加限制,不會是當前答案變優。
把上面的覆蓋別的區間的區間出去后,剩下的區間按照左端點升序排序后不難發現右端點同樣也會升序排列。
設計dp:
狀態表示:fj,if_{j,i}fj,i?考慮前iii個區間,分成jjj組的最大值
狀態轉移:fj,i=max?{fj?1,k?1+Rk?Li},Rk>Lif_{j,i}=\max\{f_{j-1,k-1}+\text R_k-\text L_i\},\text R_k>\text L_ifj,i?=max{fj?1,k?1?+Rk??Li?},Rk?>Li?
Rk>Li\text R_k>\text L_iRk?>Li?這個限制保證每組至少玩1分鐘游戲
如果沒有上述現之,可以搞一個前綴的max?{fj?1,k?1+Rk}\max\{f_{j-1,k-1}+\text R_k\}max{fj?1,k?1?+Rk?}優化轉移,加上此限制后需要單調隊列優化轉移。
Code1 暴力
895ms 竟然也能過???
#include<bits/stdc++.h> using namespace std; using ll=long long; using pii=pair<int,int>; using pli=pair<ll,int>; constexpr ll mod=1e9+7; //============================= int rd() {int res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res; } const int N=5010; int n,m; struct node {int l,r;bool operator<(const node&o)const{return l<o.l||l==o.l&&r>o.r;} }a[N],b[N]; int seg[N],cnt,tot; int f[N][N];// f[j][i] 前i個分成j組 int main() {n=rd(),m=rd();for(int i=1;i<=n;i++) b[i].l=rd(),b[i].r=rd();sort(b+1,b+1+n);int maxr=0x3f3f3f3f;for(int i=n;i;i--){if(b[i].r>=maxr) //能夠覆蓋別的線段seg[++tot]=b[i].r-b[i].l;elsemaxr=b[i].r,a[++cnt]=b[i];}sort(a+1,a+1+cnt);memset(f,-0x3f,sizeof f);f[0][0]=0;for(int j=1;j<=cnt;j++)for(int i=j;i<=cnt;i++)for(int k=1;k<=i;k++)if(a[k].r>a[i].l)f[j][i]=max(f[j][i],f[j-1][k-1]+a[k].r-a[i].l);sort(seg+1,seg+1+tot,greater<int>());int ans=0,sum=0;for(int i=0;i<=min(m,tot);i++){sum+=seg[i];if(f[m-i][cnt]!=-1) ans=max(ans,f[m-i][cnt]+sum);}cout<<ans<<'\n';return 0; }Code2 單調隊列
83ms
#include<bits/stdc++.h> using namespace std; using ll=long long; using pii=pair<int,int>; using pli=pair<ll,int>; constexpr ll mod=1e9+7; //============================= int rd() {int res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res; } const int N=5010; int n,m; struct node {int l,r;bool operator<(const node&o)const{return l<o.l||l==o.l&&r>o.r;} }a[N],b[N]; int seg[N],cnt,tot; int f[N][N];// f[j][i] 前i個分成j組 int q[N]; int main() {n=rd(),m=rd();for(int i=1;i<=n;i++) b[i].l=rd(),b[i].r=rd();sort(b+1,b+1+n);int maxr=0x3f3f3f3f;for(int i=n;i;i--){if(b[i].r>=maxr) //能夠覆蓋別的線段seg[++tot]=b[i].r-b[i].l;elsemaxr=b[i].r,a[++cnt]=b[i];}sort(a+1,a+1+cnt);memset(f,-0x3f,sizeof f);f[0][0]=0;// f[j-1][k-1] + a[k].r a[k].r>a[i].l && k<=ifor(int j=1;j<=cnt;j++){int tt=-1,hh=0;for(int i=1;i<j;i++){while(hh<=tt){int k=q[tt];if(f[j-1][i-1]+a[i].r>=f[j-1][k-1]+a[k].r) --tt;else break;}q[++tt]=i;}for(int i=j;i<=cnt;i++){while(hh<=tt) {int k=q[hh];if(a[k].r<=a[i].l) hh++;else break;}while(hh<=tt){int k=q[tt];if(f[j-1][i-1]+a[i].r>=f[j-1][k-1]+a[k].r) --tt;else break;}q[++tt]=i;int k=q[hh];f[j][i]=max(f[j][i],f[j-1][k-1]+a[k].r-a[i].l);}}sort(seg+1,seg+1+tot,greater<int>());int ans=0,sum=0;for(int i=0;i<=min(m,tot);i++){sum+=seg[i];if(f[m-i][cnt]!=-1) ans=max(ans,f[m-i][cnt]+sum);}cout<<ans<<'\n';return 0; }總結
以上是生活随笔為你收集整理的2021牛客暑期多校训练营2 G.League of Legends(转化+单调队列)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IP是互联网世界的设备入网地址,没有IP
- 下一篇: macOS如何移除和卸载第三方输入法如何