gym102302E_Chi's performance

  • 2019 年 11 月 7 日
  • 筆記

题意

给n个二元组(v,p),要求排序使得v从小到大,而且总价值最大,价值定义为相邻两个v值不同的p值之差绝对值之和。

分析

  • in a row原来是相邻的意思。
  • 对于每个相同v值的块来说,有用的数只有最大,次大,最小,次小,且如果块大小小于4,还有一些会重复,后面需要特判。
  • 所以直接dp到每个块,左端点放哪个数,右端点放哪个数能获得的最大价值。
  • 特判块大小为1的情况,以及上一个块大小为1的情况。

代码

#include <bits/stdc++.h>  using namespace std;  typedef long long ll;  const int N=1e6+50;  struct node{      int v,p;      bool operator<(const node& rhs)const{          if(v==rhs.v){              return p<rhs.p;          }else{              return v<rhs.v;          }      }  }a[N];  ll dp[N][5];  int mx[N][5],sz[N],num[N];  int n;  vector<int> v;  int main(){  //    freopen("in.txt","r",stdin);      scanf("%d",&n);      for(int i=1;i<=n;i++){          scanf("%d%d",&a[i].v,&a[i].p);          v.push_back(a[i].v);      }      sort(v.begin(),v.end());      v.erase(unique(v.begin(),v.end()),v.end());      for(int i=1;i<=n;i++){          a[i].v=lower_bound(v.begin(),v.end(),a[i].v)-v.begin()+1;      }      sort(a+1,a+1+n);      int t=1;      vector<int> tp;      tp.push_back(a[1].p);      for(int i=2;i<=n;i++){          if(a[i].v==a[i-1].v){              t++;              tp.push_back(a[i].p);          }else{              sz[a[i-1].v]=t;              if(t>=2){                  mx[a[i-1].v][3]=tp[t-1];                  mx[a[i-1].v][2]=tp[t-2];                  mx[a[i-1].v][1]=tp[1];                  mx[a[i-1].v][0]=tp[0];              }else{                  num[a[i-1].v]=a[i-1].p;              }              t=1;              tp.clear();              tp.push_back(a[i].p);          }      }      sz[a[n].v]=t;      if(t>=2){          mx[a[n].v][3]=tp[t-1];          mx[a[n].v][2]=tp[t-2];          mx[a[n].v][1]=tp[1];          mx[a[n].v][0]=tp[0];      }else{          num[a[n].v]=a[n].p;      }      int vs=v.size();      for(int i=2;i<=vs;i++){          if(sz[i]==1){              for(int j=0;j<=3;j++){                  if(sz[i-1]==1){                      dp[i][j]=dp[i-1][0]+abs(num[i]-num[i-1]);                  }else{                      for(int l=0;l<=3;l++){                          dp[i][j]=max(dp[i][j],dp[i-1][l]+abs(num[i]-mx[i-1][l]));                      }                  }              }          }else{              if(sz[i-1]==1){                  for(int j=0;j<=3;j++){                      for(int k=0;k<=3;k++){                          if(j==k || (sz[i]==2 && (j+k==2 || j+k==4)) || (sz[i]==3 && ( (j && k) && (j+k==3)))){                              continue;                          }                          dp[i][j]=max(dp[i][j],dp[i-1][0]+abs(mx[i][k]-num[i-1]));                      }                  }              }else{                  for(int j=0;j<=3;j++){                      for(int k=0;k<=3;k++){                          if(j==k || (sz[i]==2 && (j+k==2 || j+k==4)) || (sz[i]==3 && ( (j && k) && (j+k==3)))){                              continue;                          }                          for(int l=0;l<=3;l++){                              dp[i][j]=max(dp[i][j],dp[i-1][l]+abs(mx[i][k]-mx[i-1][l]));                          }                      }                  }              }          }      }      ll ans=0;      for(int i=0;i<=3;i++){          ans=max(ans,dp[vs][i]);      }      printf("%lldn",ans);      return 0;  }