2021江西省赛 D.Character Distance(思维,构造)
Posted live4m
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021江西省赛 D.Character Distance(思维,构造)相关的知识,希望对你有一定的参考价值。
题意:
解法:
设cnt[i]为数字i出现的次数,
如果存在cnt[i]=1,那么按序输出即可,这个地方特判一下.
先对序列排序.
对于数字x,两种情况
1.将<x的放完然后间隔d距离放x,最后将x以外的数按序插空即可.
2.如果情况1无法实现(剩下的距离不够放x),
那么考虑x从最后开始倒序放(可以推出倒序最优),
设r[x]表示将x倒序放之后,左边还剩下多少空位.
对于满足情况1的x,显然选择的x越大越好,取出最优的x,记为pos1,
对于不满足情况1,只满足情况2的x:(如果满足情况1肯定比情况2优,所以这里只考虑不满足情况1的)
空位越多越好,如果空位相同的数字越小越好,取出最优的x,记为pos2.
用pos1和pos2构造出两个答案,暴力比较字典序取最优解即可.
code:
#include<bits/stdc++.h>
// #define SYNC_OFF
#define int long long
#define ll long long
#define ull unsigned long long
//fast-coding
#define ST(x) x.begin()
#define ED(x) x.end()
#define RST(x) x.rbegin()
#define RED(x) x.end()
#define CL(x) x.clear();
#define all(a,n) a+1,a+1+n
#define ff(i,n) for(ll i=1;i<=n;i++)
#define rff(i,n) for(ll i=n;i>=1;i--)
#define fff(i,n) for(ll i=0;i<n;i++)
#define rfff(i,n) for(ll i=n-1;i>=0;i--)
#define SC(x) scanf("%s",x)
#define SL(x) strlen(x)
#define pss(a) push_back(a)
#define ps(a) push(a)
#define SZ(x) (int)x.size()
#define pee puts("");
#define eee putchar(' ');
#define re readdd()
#define pr(a) printtt(a)
int readdd(){int x=0,f=1;char c=getchar();//
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')f=-1,c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar();
return f*x;}
void printtt(int x){if(x<0)putchar('-'),x=-x;//
if(x>=10)printtt(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}//
int ppow(int a,int b,int mod){a%=mod;//
int ans=1%mod;while(b){if(b&1)ans=(long long)ans*a%mod;
a=(long long)a*a%mod;b>>=1;}return ans;}
bool addd(int a,int b){return a>b;}
int lowbit(int x){return x&-x;}
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};
bool isdigit(char c){return c>='0'&&c<='9';}
bool Isprime(int x){
for(int i=2;i*i<=x;i++)if(x%i==0)return 0;
return 1;
}
void ac(int x){if(x)puts("YES");else puts("NO");}
//short_type
#define VE vector<int>
#define PI pair<int,int>
//
using namespace std;
// const int mod=998244353;
const int mod=1e9+7;
const int maxm=2e6+5;
int a[maxm];
int cnt[maxm];
int ok[maxm];
int r[maxm];
int ans[2][maxm];
int n,d;
int check(){//比较字典序
ff(i,n){
if(ans[0][i]==ans[1][i])continue;
if(ans[0][i]<ans[1][i])return 0;
else return 1;
}
return 0;
}
void solve(){
n=re,d=re;
ff(i,n)a[i]=re;
sort(a+1,a+1+n);
//init
ff(i,n)ok[i]=0;
ff(i,n)ans[0][i]=ans[1][i]=0;
ff(i,n)cnt[i]=0;
ff(i,n)r[i]=-1;
//
ff(i,n)cnt[a[i]]++;
ff(i,n){
if(a[i]!=a[i-1]){//枚举x
int c=cnt[a[i]];
int len=1+(c-1)*d;
if((i-1)+len<=n){//<x的放完然后放x,是否可以放下
ok[a[i]]=1;
}
if(len<=n){//倒着放x,前面能有多少个空位
r[a[i]]=n-len;
}
}
}
int one=0;
ff(i,n){
if(cnt[i]==1)one=1;
}
if(one){
ff(i,n){
pr(a[i]);eee;
}
pee;return ;
}
//计算答案
int pos1=-1,pos2=-1;
//ok[]的取越后面的越优,因此取最后一个
ff(x,n){
if(!cnt[x])continue;
if(ok[x]){
pos1=x;
}
}
//r[]取空位最多的,如果空位相同取数字小的
ff(x,n){
if(!cnt[x])continue;
if(ok[x])continue;//ok的话不考虑pos2,pos1肯定更优
if(r[x]!=-1){
//取空位最大的,空位相同取数字小的
if(pos2==-1){
pos2=x;
}else if(r[pos2]<r[x]){
pos2=x;
}else if(r[pos2]==r[x]){
pos2=min(pos2,x);
}
}
}
// cout<<pos1<<' '<<pos2<<endl;
//
if(pos1!=-1){
int fp=0;
ff(i,n){
if(a[i]==pos1){
fp=i;break;
}
}
for(int i=1,p=fp;i<=cnt[pos1];i++,p+=d){
ans[0][p]=pos1;
}
for(int i=1,c=1;i<=n;i++){
while(ans[0][c])c++;
if(a[i]==pos1)continue;
ans[0][c++]=a[i];
}
}
if(pos2!=-1){
for(int i=1,p=n;i<=cnt[pos2];i++,p-=d){
ans[1][p]=pos2;
}
for(int i=1,c=1;i<=n;i++){
while(ans[1][c])c++;
if(a[i]==pos2)continue;
ans[1][c++]=a[i];
}
}
// cout<<pos1<<' '<<pos2<<endl;
int p=-1;
if(pos1!=-1&&pos2!=-1){
p=check();
}else if(pos1!=-1){
p=0;
}else if(pos2!=-1){
p=1;
}else{
puts("-1");return ;
}
ff(i,n){
pr(ans[p][i]);eee;
}
pee;
}
void Main(){
#define MULTI_CASE
#ifdef MULTI_CASE
int T;cin>>T;while(T--)
#endif
solve();
}
void Init(){
#ifdef SYNC_OFF
ios::sync_with_stdio(0);cin.tie(0);
#endif
#ifndef ONLINE_JUDGE
freopen("../in.txt","r",stdin);
freopen("../out.txt","w",stdout);
#endif
}
signed main(){
Init();
Main();
return 0;
}
以上是关于2021江西省赛 D.Character Distance(思维,构造)的主要内容,如果未能解决你的问题,请参考以下文章
2021年中职“网络安全“江西省赛题—B-8:Web渗透测试
2021年中职“网络安全“江西省赛题—B-2:Linux操作系统渗透测试