zoukankan      html  css  js  c++  java
  • Gym

    原题链接

    题意

    现在有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;
    }
  • 相关阅读:
    判断一个数是否为素数的方法
    什么是算法?
    table 表格
    状态模式
    设计模式
    观察者模式
    async函数
    JS单线程和异步
    ES6 --- Promise
    浅析flex 布局
  • 原文地址:https://www.cnblogs.com/fht-litost/p/7271439.html
Copyright © 2011-2022 走看看