打卡信奥刷题(3285)用C++实现信奥题 P8927 「GMOI R1-T4」Rain
P8927 「GMOI R1-T4」Rain
题目背景
求雨
玉皇爷爷也姓张,
为啥为难俺张*昌?
三天之内不下雨,
先扒龙皇庙,
再用大炮轰你娘。
如果再不下雨,张大帅就会轰掉全亚洲所有的宗教场所!
博丽神社因为可以在外界被看到,自然也无法幸免于难,灵梦十分着急,准备使用祖传秘法求雨……
题目描述
为了防止神社被“大炮开兮轰他娘”,灵梦需要求雨。
求雨需要在一条笔直的路上建 nnn 个法阵,编号为 1,2,⋯ ,n1,2,\cdots,n1,2,⋯,n。
给定一个长度为 nnn 的数组 aaa,表示在 a1a_1a1 到 ana_nan 的位置建法阵,你要干的是给法阵编号。
灵梦需要来检测法阵效果,她会从 111 号法阵走到 222 号,从 222 号再走到 333 号,直到走到 nnn 号,再从 nnn 号走回 111 号。
由于法阵的特殊效果,从 iii 个走到 i+1i+1i+1 个的距离是 ∣ai×p−ai+1×q∣\left|a_i\times p-a_{i+1}\times q\right|∣ai×p−ai+1×q∣。特别的,从 nnn 号走回到 111 号的距离是 ∣an×p−a1×q∣\left|a_n\times p-a_1\times q\right|∣an×p−a1×q∣。p,qp,qp,q 是给定的两个常数,ai,ai+1a_i,a_{i+1}ai,ai+1 是两个法阵的位置。
灵梦希望你来求一下最大的行走距离,并输出对应法阵从 111 号到 nnn 号的位置排列。(多个只需输出一个即可)
输入格式
第一行一个整数 nnn,表示法阵数量。
第二行两个整数 p,qp,qp,q,表示法阵的倍率常量。
第三行 nnn 个整数,表示数组 aaa。
输出格式
第一行一个整数,表示答案。
第二行 nnn 个整数,表示对应位置 aaa 的排列,按照编号从 111 到 nnn 输出。
输入输出样例 #1
输入 #1
10
2 3
1 2 3 4 5 6 7 8 9 10
输出 #1
131
5 6 7 1 8 2 9 3 10 4
说明/提示
本题开启 SPJ。
本题读入量较大,建议使用较快的读入方式。
对于 100%100\%100% 的数据满足 10≤n≤10610\le n\le 10^610≤n≤106,1≤p,q≤1051\le p,q \le 10^{5}1≤p,q≤105,1≤ai≤1051\le a_i\le 10^{5}1≤ai≤105。
| 编号 | nnn | p,qp,qp,q | aia_iai | 分数 |
|---|---|---|---|---|
| 111 | n=10n=10n=10 | p,q≤103p,q\le 10^{3}p,q≤103 | ai≤103a_i\le 10^{3}ai≤103 | 444 |
| 222 | n=10n=10n=10 | p,q≤103p,q\le 10^{3}p,q≤103 | ai≤103a_i\le 10^{3}ai≤103 | 555 |
| 333 | n=10n=10n=10 | p,q≤103p,q\le 10^{3}p,q≤103 | ai≤103a_i\le 10^{3}ai≤103 | 555 |
| 4∼64\sim 64∼6 | n=19n=19n=19 | p,q≤105p,q\le 10^{5}p,q≤105 | ai≤105a_i\le 10^{5}ai≤105 | 101010 |
| 777 | n≤104n\le 10^{4}n≤104 | p,q≤105p,q\le 10^{5}p,q≤105 | ai≤105a_i\le 10^{5}ai≤105 | 888 |
| 888 | n≤104n\le 10^{4}n≤104 | p,q≤105p,q\le 10^{5}p,q≤105 | ai≤105a_i\le 10^{5}ai≤105 | 999 |
| 999 | n≤104n\le 10^{4}n≤104 | p,q≤105p,q\le 10^{5}p,q≤105 | ai≤105a_i\le 10^{5}ai≤105 | 999 |
| 10∼1210\sim 1210∼12 | n≤106n\le 10^{6}n≤106 | p,q≤105p,q\le 10^{5}p,q≤105 | ai≤105a_i\le 10^{5}ai≤105 | 101010 |
C++实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c<='9'&&c>='0'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
void print(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
const int N=1e6+5,V=1e5+5;
int n,p,q,a[N],ans[N],m,p1[N],cnt1,p2[N],cnt2,sum;
bool pa[N],qa[N];
struct node{
int val,pos;
bool operator<(const node &p)const{return val<p.val;}
}tmp[N<<1];
signed main(){
n=read(),p=read(),q=read();
for(int i=1;i<=n;++i)a[i]=read(),tmp[(i<<1)-1]=(node){p*a[i],i},tmp[i<<1]=(node){q*a[i],i};
sort(tmp+1,tmp+(n<<1)+1);
for(int i=1;i<=n;++i)sum-=tmp[i].val;
for(int i=n+1;i<=(n<<1);++i){
if(tmp[i].val==p*a[tmp[i].pos])pa[tmp[i].pos]=1;
else qa[tmp[i].pos]=1;
sum+=tmp[i].val;
}
for(int i=1;i<=n;++i){
if(pa[i]^qa[i])ans[++m]=i;
else if(pa[i]&&qa[i])p2[++cnt2]=i;
else p1[++cnt1]=i;
}
for(int i=1;i<=cnt1;++i){
if(p<=q)ans[++m]=p2[i],ans[++m]=p1[i];
else ans[++m]=p1[i],ans[++m]=p2[i];
}
printf("%lld\n",sum);
for(int i=1;i<=m;++i)print(a[ans[i]]),putchar(' ');
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)