1. 程式人生 > >Gym - 100269F Flight Boarding Optimization(dp+樹狀數組)

Gym - 100269F Flight Boarding Optimization(dp+樹狀數組)

font del i++ 但是 int logs 輸出 數量 lan

原題鏈接

題意

現在有n個人,s個位置和你可以劃分長k個區域
你可以把s個位置劃分成k個區域,這樣每個人坐下你的代價是該區域內,在你之前比你小的人的數量
問你怎麽劃分這s個位置(當然,每個區域必須是連續的),才能使得總代價最小,輸出代價。

分析
dp[i][j]表示第i個位置是第j個區域的結尾,dp[i][j]→dp[t][j+1]暴力轉移。但是需要預處理每個範圍裏的代價值,需要樹狀數組維護。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1050;
int dp[maxn][55
]; int sum[maxn][maxn]; int r[maxn]; int n,m,k; int a[maxn]; vector<int> E[maxn]; int lowbit(int x) { return x&(-x); } int get(int x) { int ans = 0; for(int i=x;i;i-=lowbit(i)) ans+=a[i]; return ans; } void update(int x,int v) { for(int i=x;i<maxn;i+=lowbit(i)) a[i]
+=v; } int main() { freopen("flight.in","r",stdin); freopen("flight.out","w",stdout); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) { scanf("%d",&r[i]); E[r[i]-1].push_back(i); } for(int i=0;i<m;i++) { memset(a,
0,sizeof(a)); for(int j=i;j<m;j++) { if(i!=j)sum[i][j]=sum[i][j-1]; for(int t=0;t<E[j].size();t++) sum[i][j]+=get(E[j][t]); for(int t=0;t<E[j].size();t++) update(E[j][t],1); } } for(int i=0;i<=m;i++) for(int j=0;j<=k;j++) dp[i][j]=1e9; dp[0][0]=0; for(int i=0;i<m;i++) for(int j=0;j<k;j++) { if(dp[i][j]==1e9)continue; for(int t=i;t<m;t++) dp[t+1][j+1]=min(dp[t+1][j+1],dp[i][j]+sum[i][t]); } cout<<dp[m][k]<<endl; }

Gym - 100269F Flight Boarding Optimization(dp+樹狀數組)