题目描述:
小Z有一个长度为的数列。他有次令人窒息的操作,每次操作可以使某个数字或。他当然是希望这些数字的乘积尽量小了。为了简化题目,你只需输出操作完成后的数列即可。
————————————————我是分割线————————————————
这道题目,我们可以先自己手动模拟一遍,就能发现,首先我们需要尽量让乘积最小,那么首先我们希望乘积为负数,
所以假设一开始的时候乘积为整数,我们先拿出绝对值最小的那个数,如果是正数就-x,如果是负数就+x直到乘积变为负数。
在乘积变为负数之后,我们来看一个问题:
3 4 6 3个数中,在任意一个数上+1,问加在哪个数的时候,使他们的乘积增加最大?显然是3。所以在乘积为负的时候,我们每次取绝对值最小的数让他的绝对值变大即可
下面贴代码
#include<cstdio> #include<queue> #include<algorithm> using namespace std; long long aqs(long long a){return a>=0?a:-a;} struct number{ long long num,opt; friend bool operator <(number a,number b){ if(aqs(a.num)==aqs(b.num))return a.num>b.num; return aqs(a.num)>aqs(b.num); } }qaq[200005]; int zheng=1,n,k,x; priority_queue<number>q; bool cmp(number a,number b){ return a.opt<b.opt; } int main(){ scanf("%lld%lld%lld",&n,&k,&x); for(int i=1;i<=n;i++){ scanf("%lld",&qaq[i].num); qaq[i].opt=i; q.push(qaq[i]); if(qaq[i].num<0)zheng=(zheng==1)?0:1; } for(int i=1;i<=k;i++){ number tmp=q.top(); q.pop(); if(zheng==1){ bool now=(tmp.num>=0); if(now)tmp.num-=x;else tmp.num+=x; q.push(tmp); if((tmp.num<0&&now)||(tmp.num>0&&!now))zheng=0; } else { if(tmp.num>=0){ tmp.num+=x; q.push(tmp); } else tmp.num-=x,q.push(tmp); } } for(int i=1;i<=n;i++){ qaq[i]=q.top();q.pop(); } sort(qaq+1,qaq+n+1,cmp); for(int i=1;i<n;i++)printf("%lld ",qaq[i].num); printf("%lld ",qaq[n].num); return 0; }