2017 TCO Algorithm Round 2C - Division I, Level Three TreasureOfWinedag 題解
阿新 • • 發佈:2021-07-02
TreasureOfWinedag 題解
最終答案一定在區間\([k,k+25]\)之間。
考慮暴力dp,\(dp_{i,j}\)表示考慮了前i個字元,分成了恰好k段的方案數。
\(dp_{i,j}\in [j,j+25]\),設\(f_{i,j}=dp_{i,j}-j\) ,\(f_{i,j}\in [0,25]\)。
可以發現\(f_{i,j}\)遞減,因為\(dp_{i,j}\)隨著\(j\)遞增,但是最多增加1。
考慮對\(f\)進行\(dp\),\(f_{i,j}=\min\{f_{k,j-1}+cost(k+1,i)-1\}\)。
由於\(cost(k+1,i)\)的取值有限,所以列舉\(cost(k+1,j)\)
令\(g_{i,k}\)表示最小的\(j\),滿足\(f_{i,j}\leq k\)。
可以直接對其dp。
code:
/* { ###################### # Author # # Gary # # 2021 # ###################### */ #include<bits/stdc++.h> #define rb(a,b,c) for(int a=b;a<=c;++a) #define rl(a,b,c) for(int a=b;a>=c;--a) #define LL long long #define IT iterator #define PB push_back #define II(a,b) make_pair(a,b) #define FIR first #define SEC second #define FREO freopen("check.out","w",stdout) #define rep(a,b) for(int a=0;a<b;++a) #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()) #define random(a) rng()%a #define ALL(a) a.begin(),a.end() #define POB pop_back #define ff fflush(stdout) #define fastio ios::sync_with_stdio(false) #define check_min(a,b) a=min(a,b) #define check_max(a,b) a=max(a,b) using namespace std; //inline int read(){ // int x=0; // char ch=getchar(); // while(ch<'0'||ch>'9'){ // ch=getchar(); // } // while(ch>='0'&&ch<='9'){ // x=(x<<1)+(x<<3)+(ch^48); // ch=getchar(); // } // return x; //} const int INF=0x3f3f3f3f; typedef pair<int,int> mp; /*} */ const int MAXN=1e5+1; int g[MAXN][26],pre[26],P[26]; int f(int i,int j){ if(j>i) return INF; if(i==0) return 0; if(j==0) return INF; int l=0,r=25; while(l<r){ int mid=(l+r)>>1; if(g[i][mid]<=j) r=mid; else l=mid+1; } return l; } int queryg(int i,int j){ int ans=INF; rep(k,26){ if(k<=j) check_min(ans,g[P[k]-1][j-k]+1); } return ans; } class TreasureOfWinedag{ public: int solvePuzzle(int n, int k, int m, int c0,vector<int> c1, vector<int> c2, vector<int> c3, vector<int> c4, string s){ rb(i,s.length(),n-1){ int t = (1ll*i * c0) % m; char nc = 'z'; rep(j,25) if ((t >= c3[j]) and (t <= c4[j]) and ((t % c1[j]) == c2[j])){ nc='a'+j; break; } s.PB(nc); } s='$'+s; rb(i,1,n){ int ch=s[i]-'a'; pre[ch]=i; vector<int> pos; rep(j,26) if(pre[j]) pos.PB(pre[j]+1); sort(ALL(pos)); reverse(ALL(pos)); rep(j,pos.size()){ if(j){ P[j-1]=pos[j]; } } P[pos.size()-1]=1; rep(j,26){ g[i][j]=queryg(i,j); } } return f(n,k)+k; } }solver;