https://codeforces.com/contest/1256/problem/E
n,m,d<=1000 复杂度O(n2)
贪心 木板跳
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll n,m,d,t;
ll c[maxn],ans[maxn];
int main(){
cin>>n>>m>>d;
for(int i=1;i<=m;i++)
cin>>c[i];
ll pos=n;
for(int i=m;i>=1;i--){
for(int j=0;j<c[i];j++){
ans[pos-j]=i;
}
pos-=c[i];
}
ll now=0;
while(true){
while(now+1<n+1 && ans[now+1]>0) now++; //now肯定在木板上 往最右端移动
if(now+d>=n+1) break; // n=1 d=2 0 0->2
if(ans[now+d]==0){
ll lpos=-1;
for(int i=now+d;i<n+1;i++){
if(ans[i]!=0){
lpos=i;
break;
}
}
if(lpos==-1){
return cout<<"NO"<<endl,0;//后面没有木板
}
ll rpos=-1;
for(int i=lpos;i<n+1;i++){
if(ans[i]==ans[lpos]) rpos=i;
}
while(ans[now+d]==0){ //now+d到不了有木板的地方 找后面第一个木板位置
swap(ans[rpos],ans[lpos-1]);
rpos--;
lpos--;//一直交换
}
}
now+=d;
}
cout<<"YES"<<endl;
for(int i=1;i<=n;i++){
cout<<ans[i];
if(i!=n)
cout<<" ";
}
cout<<endl;
return 0;
}
B
位置相互交换 每个位置只能用1次 至多n-1次操作
使得字典序最小
4
5
5 4 1 3 2
4
1 2 4 3
1
1
4
4 3 2 1
1 5 2 4 3
1 2 3 4
1
1 4 3 2
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef long long ll;
const ll inf=2e18;
ll q,m,k,n,cnt,t,minn,maxx;
string s;
ll a[maxn],vis[maxn];
int main(){
cin>>q;
while(q--){
cin>>n;
ll p=0,pos=0;
cnt=n-1;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]==1){
p=i;
}
}
if(p!=1){
ll num=a[p];
for(int i=p-1;i>=1;i--){
a[i+1]=a[i];
}
a[1]=num;
// for(int i=1;i<=n;i++){
// cout<<a[i]<<" ";
// }
// cout<<endl;
cnt-=(p-1);
}
else
p++;
// cout<<cnt<<endl;
// cout<<p<<endl;
for(int i=p;i<=n && cnt>0;i++){
minn=1000;pos=0;
for(int j=p;j<=n;j++){
if(a[j]<minn){
minn=a[j];
pos=j;
}
}
// cout<<pos<<" "<<minn<<endl;
if(pos!=i){
ll num=min(cnt,pos-p);
cnt-=num;
ll s=a[pos];
for(int i=pos-1;i>=pos-num;i--){
a[i+1]=a[i];
}
a[p]=s;
p=pos;
}
else
p++;
}
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
}
return 0;
}
F 字符串
将s串长为len子串倒置
将t串长为len子串也倒置
最终是否能使s,t相等
考虑长度为2的互换
排序后对应位置不等 X
如果有些顺序差异 抵消后使得只有其中1串
如果存在 连续相邻两个相等 YES
否则差为奇数 且无连续两个倒置不变的情况 NO
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll n,q,f,flag;
string s,t;
ll sum1,sum2;
ll cnt1[26],cnt2[26];
int main(){
cin>>q;
while(q--){
sum1=0;sum2=0;f=0;flag=0;
for(int i=0;i<=25;i++){
cnt1[i]=0;
cnt2[i]=0;
}
cin>>n>>s>>t;
for(int i=0;i<n;i++) {
cnt1[s[i]-'a']++;
cnt2[t[i]-'a']++;
for(int j=s[i]-'a';j<=25;j++){
sum1+=cnt1[j];
}
for(int j=t[i]-'a';j<=25;j++){
sum2+=cnt2[j];
}
}
// cout<<sum1<<" "<<sum2<<endl;
sort(s.begin(),s.end());
sort(t.begin(),t.end());
for(int i=0;i<n;i++){
if(s[i]!=t[i]){
f=1;
break;
}
}
if(f)
{
cout<<"NO"<<endl;
continue;
}
for(int i=1;i<n;i++){ //排序后对应位置相等
if(s[i]==s[i-1]){//原先顺序不对 只差1 但只要有两个相邻的
flag=1;
break;
}
}
if(flag){
cout<<"YES"<<endl;
continue;
}
if((sum1-sum2)&1) //差值为奇数 且没有相邻的互换
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}