Codeforces Problem - 1016C

Codeforces Problem - 1016C

[http://codeforces.com/problemset/problem/1016/C]



题意:一个N,2×N 个数,从[1, 1]点开始将所有点全部遍历完,输出遍历的最大值。遍历的规则是(遍历的顺序-1)×当前的那个数。

题解:使用前缀和解决这个问题,思路是将N分成两块,左边是一上一下的折叠状,右边的是直走再转回来那种。求前缀和优化思路就好。
题目非常灵活有很多可以优化的地方。

#include <cstdio>
using namespace std;
typedef long long ll;
const int MAXN = 3e5+5;
ll dp[MAXN][2]={0};
ll step[MAXN][2]={0};
ll dis[MAXN*2][2]={0};
ll vis[MAXN*2][2]={0};
ll num[MAXN][2];
ll max(ll a,ll b){
    return a>b?a:b;
}
ll odd(int x,int N){
    ll res=dp[x][0],cnt=step[x][0]+1;
    res+=dis[N*2-1-x][0]-dis[x][0]+(vis[2*N-1-x][0]-vis[x][0])*(cnt-x-1);
    return res;
}
ll even(int x,int N){
    ll res=dp[x][1],cnt=step[x][1]+1;
    res+=dis[N*2-1-x][1]-dis[x][1]+(vis[2*N-1-x][1]-vis[x][1])*(cnt-x-1);
    return res;
}
int main(){
    int N;
    scanf("%d",&N);
    for(int i=0;i<2;i++){
        for(int j=0;j<N;j++){
            scanf("%d",&num[j][i]);
            dp[j][i]=num[j][i];
        }
    }
    ll cnt=0;
    int x=0,y=0;
    dp[0][0]=0;
    while(cnt<2*N){
        int dx=x,dy=y;
        if(y==0){
            if(x%2==0)y=1;
            else x++;
        }
        else{
            if(x%2==0)x++;
            else y=0;
        }
        dp[x][y]=dp[x][y]*(cnt+1)+dp[dx][dy];
        step[x][y]=cnt+1;
//        printf("%d %d %d\n",x,y,dp[x][y]);
        cnt++;
    }

    for(int i=0;i<N;i++){
        vis[i][0]=num[i][0];
        vis[i][1]=num[i][1];
    }
    for(int i=0;i<N;i++){
        vis[i+N][0]=num[N-i-1][1];
        vis[i+N][1]=num[N-i-1][0];
    }
    for(int i=0;i<2*N;i++){
        dis[i][0]=vis[i][0]*i;
        dis[i][1]=vis[i][1]*i;
        if(i){
            dis[i][0]+=dis[i-1][0];
            dis[i][1]+=dis[i-1][1];
            vis[i][0]+=vis[i-1][0];
            vis[i][1]+=vis[i-1][1];
        }
    }
//    for(int i=0;i<2;i++){
//        for(int j=0;j<2*N;j++)
//            printf("%d ",vis[j][i]);
//        printf("\n");
//    }
//    for(int i=0;i<2;i++){
//        for(int j=0;j<2*N;j++)
//            printf("%d ",dis[j][i]);
//        printf("\n");
//    }
//    for(int i=0;i<2;i++){
//        for(int j=0;j<N;j++){
//            printf("%lld ",dp[j][i]);
//        }
//        printf("\n");
//    }
//    for(int i=0;i<2;i++){
//        for(int j=0;j<N;j++)
//            printf("%lld ",step[j][i]);
//        printf("\n");
//    }
    ll maxx=dp[N-1][N%2];
    for(int i=0;i<N;i++){
        if(i%2==0)maxx=max(maxx,odd(i,N));
        if(i%2==1)maxx=max(maxx,even(i,N));
    }
    printf("%lld\n",maxx);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Vagrant-ac/p/12241658.html