https://codeforces.com/contest/2038/problem/I
n个运动员,m个运动项目。用一个01字符串表示运动员擅长的项目。
求从第i个项目开始循环往后m次比较,最后谁胜出(如果不擅长则被淘汰,如果这个项目没人擅长,则跳过)。
1.循环,于是乘2
2.即求从第i个点开始的,长度为m的子串,排序后谁最大。
3.基数排序 LSD排序 LSD排序
从后往前遍历,cnt记录当前排了多少个数。dp[2][n]记录上一次排序结果和这一次排序结果。因为只有0和1。根据上一次排序结果,从小到大遍历所有数,如果当前位是0,按顺序排入。再同样从小到大遍历所有数,按顺序排入。就得到当前位排序结果。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
void solve(){
int n,m; cin>>n>>m;
string s[n+1];
for(int i=0;i<n;i++){
cin>>s[i]; s[i] = s[i]+s[i];
}
int dp[2][n+1],used[n+1],ans[m+1];
for(int i=0;i<n;i++) dp[0][i] = i;
for(int i=2*m-1;i>=0;i--){
for(int j=0;j<n;j++){
used[j] = s[j][i] - '0';
}
int cnt = 0;
for(int j=0;j<n;j++){
if(used[dp[(i+1)&1][j]]==0) dp[i&1][cnt++] = dp[(i+1)&1][j];
}
for(int j=0;j<n;j++){
if(used[dp[(i+1)&1][j]]==1) dp[i&1][cnt++] = dp[(i+1)&1][j];
}
if(i<m){
ans[i] = dp[i&1][n-1];
}
}
for(int i=0;i<m;i++) cout<<ans[i]+1<<" ";
}
int main(){
ifstream test_file("in.txt");
if (test_file) {
freopen("in.txt", "r", stdin);
freopen("output.txt", "w", stdout);
}
std::ios::sync_with_stdio(0);std::cout.tie(0);std::cin.tie(0);
int T = 1;
#ifdef MULTI_TEST
cin>>T;
#endif
while(T--){
solve();
}
return 0;
}