2019杭電多校第一場

6581 Vacation

題意

從右到左分別爲0-n輛車,每輛車有長度l,起始位置s和速度v,0座標在左邊,不能超車,單車道,問0號車到達0座標的最短期。html

分析

最短期考慮二分時間,而後按這個時間從左邊第一輛車開始依次計算最終位置,最後判斷0號車的位置便可。c++

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const double eps=1e-12;
int l[N],s[N],v[N];
int n;
bool check(double t){
    //判斷時間t car可否經過紅綠燈
    //第一輛車全速
    double st=1.0*s[n]-1.0*v[n]*t;
    double ed=st+l[n];
    for(int i=n-1;i>=0;i--){
        double tst=1.0*s[i]-1.0*v[i]*t;
        st=max(ed,tst);
        ed=st+l[i];
    }

    return st<=0;
}
int main(void){
    // freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)){
        for(int i=0;i<=n;i++){
            scanf("%d",&l[i]);
        }
        for(int i=0;i<=n;i++){
            scanf("%d",&s[i]);
        }
        for(int i=0;i<=n;i++){
            scanf("%d",&v[i]);
        }
        double l=0.0,r=1e9;
        double ans;
        while(fabs(l-r)>=eps){
            double mid=(l+r)/2;
            if(check(mid)){
                ans=mid;
                r=mid;
            }else{
                l=mid;
            }
        }
        printf("%.10lf\n",ans);
    }
    return 0;
}

6582 Path

具體見 http://www.javashuo.com/article/p-sytkfemy-gb.htmlxcode

6586 String

題意

給一個字符串,以及每一個字符出現次數的限制,找到長度爲k的字典序最小的且知足次數限制的子序列。spa

分析

序列自動機預處理出每一個位置後面每一個字符第一次出現的位置和個數,而後每次取出知足條件的最小字符,即取了該字符後,剩下的字符串也要知足最小條件。code

不知足條件的狀況多是htm

  • 後面某個字符全選也不能知足下限
  • 後面字符數不能知足下限
  • 該字符已選超過上限
  • 選了該字符後,雖然剩下字符單獨都能知足限制,但總數不夠

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
char s[N];
int k;
int l[26],r[26],v[26];
int nxt[N][26],cnt[N][26];
int main(void){
    // freopen("in.txt","r",stdin);
    while(~scanf("%s%d",s+1,&k)){
        for(int i=0;i<26;i++){
            v[i]=0;
            scanf("%d%d",&l[i],&r[i]);
        }
        int n=strlen(s+1);
        for(int i=0;i<26;i++){
            nxt[n][i]=cnt[n][i]=0;
        }
        //序列自動機預處理出每一個位置後面每一個字符第一次出現的位置和個數
        for(int i=n-1;i>=0;i--){
            for(int j=0;j<26;j++){
                nxt[i][j]=nxt[i+1][j];
                cnt[i][j]=cnt[i+1][j];
            }
            nxt[i][s[i+1]-'a']=i+1;
            cnt[i][s[i+1]-'a']++;
        }
        bool flag=true;
        string ans="";
        int t=0;
        //每次貪心取最小的,判斷剩下後綴可否知足要求
        for(int i=0;i<k;i++){
            int j=0;
            //從小到大枚舉字符,選擇可選的
            for(;j<26;j++){
                if(cnt[t][j]){
                    int g=nxt[t][j];
                    bool ac=true;
                    //嘗試選擇
                    v[j]++;
                    //記錄後面還須要每種字符的總個數
                    int ned=0;
                    for(int q=0;q<26;q++){
                        //選的數量可能會超過l[q]
                        ned+=max(0,l[q]-v[q]);
                        //後面的該字符個數不夠下限 || 剩下的可選字符數不夠下限  || 該字符已選個數大於上限
                        if(cnt[g][q]<l[q]-v[q] || k-i-1<l[q]-v[q] || v[q]>r[q]){
                            ac=false;
                            break;
                        }
                    }
                    //雖然選了這個字符以後,剩餘後綴每一個字符數量都能知足限制,但加起來總數不夠
                    if(k-i-1<ned){
                        ac=false;
                    }
                    v[j]--;
                    if(ac){
                        ans+=(char)('a'+j);
                        v[j]++;
                        t=g;
                        break;
                    }
                }
            }
            if(j==26){
                flag=false;
                break;
            }
        }
        if(flag){
            printf("%s\n",ans.c_str());
        }else{
            printf("-1\n");
        }
    }
    return 0;
}
相關文章
相關標籤/搜索