CF573D-Bear and Cavalry【动态dp】
生活随笔
收集整理的這篇文章主要介紹了
CF573D-Bear and Cavalry【动态dp】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/CF573D
題目大意
給出nnn個人nnn匹馬,每個人/馬有能力值wiw_iwi?/hih_ihi?。
第iii個人開始對應第iii匹馬,每個人不能選擇對應的馬,給每個人分配一個馬后求最大的∑wi×hj\sum w_i\times h_j∑wi?×hj?。
每次交換兩個人對應的馬后求答案。
1≤n≤30000,1≤q≤100001\leq n\leq 30000,1\leq q\leq 100001≤n≤30000,1≤q≤10000
解題思路
設fif_ifi?表示匹配完前iii匹馬時的最大價值和。
考慮怎么轉移,因為人和馬一一對應,正常來說大的對大的乘積的和最大。但是如果恰好第iii個人對應了第iii匹馬,那么顯然iii只能選擇i+1i+1i+1,而讓i+1i+1i+1選擇iii。
然后還有一種情況是只有三個時,第一個人對應了第一匹馬,上面的轉移會使得最后一個人和最后一匹馬無法匹配,故我們還需要考慮和第三個的匹配。
也就是fif_ifi?只會從fi?1,fi?2,fi?3f_{i-1},f_{i-2},f_{i-3}fi?1?,fi?2?,fi?3?轉移過來,所以上動態dpdpdp即可
時間復雜度O(33nlog?n)O(3^3n\log n )O(33nlogn)
code
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=31000,inf=1e18,S=3; struct matrix{ll a[S][S]; }w[N<<4],c,tt; struct node{ll p,w; }e[N],h[N]; ll n,m,id[N]; matrix operator*(const matrix &a,const matrix &b){memset(c.a,0xcf,sizeof(c.a));for(ll i=0;i<S;i++)for(ll j=0;j<S;j++)for(ll k=0;k<S;k++)c.a[i][j]=max(c.a[i][j],a.a[i][k]+b.a[k][j]);return c; } bool cmp(node x,node y){return x.w>y.w;} void Change(ll x,ll L,ll R,ll pos,matrix &val){if(L==R){w[x]=val;return;}ll mid=(L+R)>>1;if(pos<=mid)Change(x*2,L,mid,pos,val);else Change(x*2+1,mid+1,R,pos,val);w[x]=w[x*2]*w[x*2+1]; } ll calc(ll l,ll r){if(l<=0)return -inf;ll n=r-l+1,c[4]={0,1,2,0},ans=-inf;do{ll sum=0;for(ll j=0;j<n;j++){if(e[l+c[j]].p==h[l+j].p){sum=-inf;break;}sum=sum+e[l+c[j]].w*h[l+j].w;}ans=max(ans,sum);}while(next_permutation(c,c+n));return ans; } void Updata(ll x){if(x>n)return;memset(tt.a,0xcf,sizeof(tt.a));tt.a[1][0]=0;tt.a[2][1]=0;tt.a[0][2]=calc(x-2,x);tt.a[1][2]=calc(x-1,x);tt.a[2][2]=calc(x,x);Change(1,1,n,x,tt);return; } signed main() {scanf("%lld%lld",&n,&m); // memset(tt.a,0xcf,sizeof(tt.a)); // tt.a[0][0]=tt.a[1][1]=tt.a[2][2]=0; // for(ll i=1;i<(N<<2);i++)w[i]=tt[i];for(ll i=1;i<=n;i++)scanf("%lld",&e[i].w),e[i].p=i;for(ll i=1;i<=n;i++)scanf("%lld",&h[i].w),h[i].p=i;sort(e+1,e+1+n,cmp);sort(h+1,h+1+n,cmp);for(ll i=1;i<=n;i++)id[e[i].p]=i;for(ll i=1;i<=n;i++)Updata(i);while(m--){ll l,r;scanf("%lld%lld",&l,&r);l=id[l];r=id[r];swap(e[l].p,e[r].p);for(ll i=0;i<3;i++)Updata(l+i),Updata(r+i);printf("%lld\n",w[1].a[2][2]);}return 0; }總結
以上是生活随笔為你收集整理的CF573D-Bear and Cavalry【动态dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神秘星球孪生公主
- 下一篇: AT5661-[AGC040C]Neit