CodeForces - 1256D (贪心+思维)
题意
给定一个长度为n的二进制串(即由n个'0'和'1'构成的字符串),你最多可以进行k次交换相邻两个字符的操作,求字典序最小的串。
思路
大致就是找0的位置,然后贪心的放到最前面,这样字典序会最小:
代码
我的丑做法:
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=200005; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) int main() { std::ios::sync_with_stdio(false); int t; cin>>t; while(t--) { ll n,k; cin>>n>>k; string s; cin>>s; int l=s.length(); queue<int> q; for(int i=0; i<l; i++) { if(s[i]=='0') { q.push(i); } } ll sum=0,tmp=0,cnt=0,lst=0,flag=0; while(!q.empty()) { int f=q.front(); sum+=(f-tmp); if(sum>k) { sum-=(f-tmp); flag=1; break; } lst=f; tmp++; cnt++; q.pop(); } // cout<<sum<<" "<<lst<<" "<<cnt<<endl; if(!flag) { for(int i=0;i<cnt;i++) cout<<0; for(int i=0;i<n-cnt;i++) cout<<1; cout<<endl; continue; } // cout<<cnt<<endl; string ans; for(int i=0; i<cnt; i++) { ans+="0"; } for(int i=0; i<lst-cnt+1; i++) ans+="1"; int num=lst-cnt+1+cnt; // cout<<"h:"<<num<<endl; for(int i=num; i<l; i++) { num++; ans+=s[i]; if(s[i]=='0') { break; } } // cout<<"g:"<<num<<endl; for(int i=0; i<k-sum; i++) { swap(ans[num-i-1],ans[num-i-2]); } for(int i=num; i<l; i++) ans+=s[i]; cout<<ans<<endl; } return 0; }
简单做法(太强了):
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=1e6+5; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) char s[N]; int main() { std::ios::sync_with_stdio(false); int t; ll n,k; cin>>t; while(t--) { cin>>n>>k; cin>>s+1; ll l=strlen(s+1),cnt=0; for(ll i=1;i<=l;i++) { if(s[i]=='0') { cnt++; if(k>i-cnt) { swap(s[i],s[cnt]); k-=(i-cnt); } else { swap(s[i],s[i-k]); break; } } } cout<<s+1<<endl; } return 0; }