• XJOI网上同步训练DAY1 T3


    思路:一开始看到这题的时候想DP,可是发现貌似不行。。因为有前缀也有后缀,而且有的后缀会覆盖到现在的前缀,这就不满足无后效性了啊!

    但是有个很巧妙的思路:如果我们知道a[i]的最大值,那么p的数量和q的数量也确定了。所以序列长度也确定了,设m为序列长度。

    而且对于每个a[i]都代表了一个固定数量的p和q和长度。

    因此,长度大于m/2的前缀,我们可以用总的p和总的q减去它,转换成小于等于m/2长度的前缀后缀。

    这样我们可以设计DP为f[i][j][k],代表从左往右i个中有j个p,从右往左i个有k个p,这样f[(m+1)/2]的位置就是最终答案!

    注意要记录一个pre数组记录这个状态的最优解是从哪个位置转移过来的。

      1 #include<algorithm>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<iostream>
      6 #define ll long long
      7 ll a[200005];
      8 const ll PW=9705276;
      9 const ll QW=12805858;
     10 int c[200005][2],n,pre[205][205][205][2],w[205][205],f[205][205][205];
     11 int ans[200005],cn;
     12 int read(){
     13     char ch=getchar();int t=0,f=1;
     14     while (ch<'0'||'9'<ch){if (ch=='-') f=-1;ch=getchar();}
     15     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
     16     return t*f;
     17 }
     18 void init(){
     19     n=read();
     20     for (int i=0;i<n;i++){
     21         double x;scanf("%lf",&x);
     22         a[i]=(ll)(x*100000+0.5);
     23     }
     24 }
     25 void solve(){
     26     int mxpos=0;
     27     for (int i=1;i<n;i++){
     28         if (a[i]>a[mxpos]) mxpos=i;
     29     }
     30     int totp=-1,totq=-1;
     31     for (int i=0;(ll)i*PW<=a[mxpos];i++)
     32      if ((a[mxpos]-(ll)i*PW)%QW==0){
     33             totp=i;
     34             totq=(int)((a[mxpos]-(ll)i*PW)/QW);
     35             break;
     36     }
     37     for (int i=0;i<n;i++){
     38         int p=-1,q=-1;
     39         for (int j=0;(ll)j*PW<=a[i];j++)
     40          if ((a[i]-(ll)j*PW)%QW==0){
     41                 p=j;
     42                 q=(int)((a[i]-(ll)j*PW)/QW);
     43                 break;
     44          }
     45          if (p!=-1&&p+q<=totp+totq){
     46                 c[cn][0]=p;
     47                 c[cn][1]=q;
     48                 cn++;
     49          }
     50     }
     51     int m=totp+totq;
     52     for (int i=0;i<cn;i++){
     53         if (c[i][0]+c[i][1]<=m/2){
     54             w[c[i][0]+c[i][1]][c[i][1]]++;
     55         }else{
     56             w[m-c[i][0]-c[i][1]][totq-c[i][1]]++;
     57         }
     58     }
     59     f[0][0][0]=0;
     60     for (int i=1;i<=m/2;i++)
     61      for (int j=0;j<=i;j++)
     62       for (int k=0;k<=i;k++){
     63             int s=-1;
     64             for (int p=0;p<=1;p++){
     65                 for (int q=0;q<=1;q++){
     66                     if (j-p>=0&&j-p<i&&k-q>=0&&k-q<i&&f[i-1][j-p][k-q]>s){
     67                         s=f[i-1][j-p][k-q];
     68                         pre[i][j][k][0]=p;
     69                         pre[i][j][k][1]=q;
     70                     }
     71                 }
     72             }
     73             f[i][j][k]=s+w[i][j]+((k==j)?0:w[i][k]);
     74       }
     75     int ansi=-1,ansj=-1,ansk=-1;
     76     for (int k=0;k<=m%2;k++)
     77      for (int i=0;i<=m/2;i++){
     78         int j=totq-k-i;
     79         if (j>=0&&j<=m/2&&(ansi==-1||f[m/2][i][j]>f[m/2][ansi][ansj])){
     80             ansi=i;
     81             ansj=j;
     82             ansk=k;
     83         }
     84     }
     85     if (m%2) ans[m/2]=ansk;
     86     for (int i=m/2;i>0;i--){
     87         int p=pre[i][ansi][ansj][0];
     88         int q=pre[i][ansi][ansj][1];
     89         ans[i-1]=p;
     90         ans[m-i]=q;
     91         ansi-=p;
     92         ansj-=q;
     93     }
     94     for (int i=0;i<m;i++)
     95      if (ans[i]) printf("Q");
     96      else printf("P");
     97 }
     98 int main(){
     99     init();
    100     solve();
    101 }
  • 相关阅读:
    用户使用调查报告
    Beta总结
    Beta冲刺Day7
    Beta冲刺Day6
    Beta冲刺Day5
    Beta冲刺Day4
    Beta冲刺Day3
    Beta冲刺Day2
    Beta冲刺Day1
    Beta预备
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5615145.html
Copyright © 2020-2023  润新知