当前位置: 首页 > news >正文

Error Swap_arc198c分析与解答

C - Error Swap

操作在交换的基础上增加了加减1,首先可以发现,操作前后数组的所有数的和不变,因此如果初始时a数组元素的和不等于b数组元素的和,则a不可能变成b。

其实只要a数组元素的和等于b数组元素的和,a就一定能变成b,(其实还需要n>2,因为需要进行交换操作,请往下看),因为当对a_i和a_j (i<j)先交换再进行一次操作,可以让a_i减少1,让a_j增加1,若i>j,则先进行一次操作再交换,就也可以让a_i减少1,a_j增加1,而a数组元素的和与b数组元素的和相等的话,a中元素需要减少的量和需要增加的量是相等的,不断选出a_i和a_j,其中a_i是需要减小的元素,a_j是需要增大的元素,进行对a_i+1,对a_j-1的操作最终就可以让a_i等于b_i让a_j等于b_j。

但交换的操作如何实现呢?先看看有两个元素的情况,如果n=2,那么

a1,a2只能变成a2-1,a1+1,因为再变就又回到a1,a2,是无法实现交换操作的。n=2的情况我们特判。

n>2时,如果要交换a_i和a_j (i<j),可以借助第三个元素完成,如果i>1,可以借助他们左边的元素a_1完成:

用(a,b)(a<b)表示对a位置和b位置上的元素进行操作。

依次进行操作:(1,i) (1,j) (1,i)

如果i>1不满足,其实借助这两个元素右边的元素a_n也可以:
依次操作:(i,n) (j,n) (i,n)

如果i=1并且j=n,那能不能借助两个元素中间的元素对i,j进行交换?答案是可以,但是相较于以上两种交换的操作方式,这种交换的操作方式可能不那么直接想到,需要构造,可以按如下思路:

用a_i和a_j之间的a_p进行中转,i<p<j,最后一次操作对位置i,j进行,也就是最后一次操作是(i,j),那么最后一次操作前,i 位置上的值应该是a_i-1,j 位置上的值应该是a_j+1,如果将a_i向右换一次,向左换两次,就得到值a_i-1,同样将a_j向左换一次,向右换两次,得到值a_j+1,这一过程可以这样完成:
(i,j) (i,p) (p,j) (i,p)

加上最后的(i,j)的话,用p为中转交换(i,j)的操作序列是:
(i,j) (i,p) (p,j) (i,p) (i,j)

当i=1,j=n时,可以用2作为中转,写成:
(1,n) (1,2) (2,n) (1,2) (1,n)

现在分析一下总共需要的操作次数,让每个a_i和b_i的差值(差的绝对值)都最大,则总差值为nm,则需要进行mn/2次的a_i->a_i-1,a_j->a_j+1(记作“改变值”),如果让这mn/2次的改编自中,有尽量多的i=1和j=n,这样最后的总操作数会更大,那么在这mn/2次改变值中,最多有m/2次是对1和n改变值,所以总操作次数为:
mn/2*(交换需要3次+操作的1次)+(mn/2-m/2)*(交换需要5次+操作的1次),小于题目要求的31000。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;const ll maxn=100+5;
ll n;
ll a[maxn],b[maxn];
vector<pair<ll,ll>> op;void opt(ll x,ll y){if(x>y) swap(x,y);op.push_back({x,y});ll t=a[x];a[x]=a[y]-1;a[y]=t+1;
}void swp(ll x,ll y){if(y<x) swap(x,y);if(x>1) {opt(1,x);opt(1,y);opt(1,x);}else if(y<n){opt(n,x);opt(n,y);opt(n,x);}else {opt(1,n);opt(1,2);opt(2,n);opt(1,2);opt(1,n);}
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cin>>n;ll s1=0,s2=0;for(ll i=1;i<=n;i++) {cin>>a[i];s1+=a[i];}for(ll i=1;i<=n;i++) {cin>>b[i];s2+=b[i];}if(n==2){if(a[1]==b[1] && a[2]==b[2]) {cout<<"Yes"<<"\n";cout<<0<<"\n";}else if(a[2]-1==b[1] && a[1]+1==b[2]){cout<<"Yes"<<"\n";cout<<1<<"\n";cout<<1<<" "<<2<<"\n";}else {cout<<"No"<<"\n";}}else {if(s1!=s2) {cout<<"No"<<"\n";}else {cout<<"Yes"<<"\n";op.clear();vector<ll> p,q;for(ll i=1;i<=n;i++){ll d=a[i]-b[i];if(d>0) {for(ll j=1;j<=d;j++) p.push_back(i);}else if(d<0){d=-d;for(ll j=1;j<=d;j++) q.push_back(i);}}//printf("p大小:%lld q大小:%lld\n",p.size(),q.size());for(ll i=0;i<p.size();i++){ll x=p[i],y=q[i];if(x<y) {swp(x,y);opt(x,y);}else {opt(x,y);swp(x,y);}}/*printf("Seq after operations:\n");for(ll i=1;i<=n;i++) cout<<a[i]<<" ";cout<<"\n";*/cout<<(ll)op.size()<<"\n";for(ll i=0;i<op.size();i++){cout<<op[i].first<<" "<<op[i].second<<"\n";}}}return 0;
}

相关文章:

  • 如何做支付接口呢?
  • 论文阅读笔记——In-Context Edit
  • ETL怎么实现多流自定义合并?
  • [AD] Noxious LLMNR+DHCP+NTLMv2+Kerberos+SMB
  • 智慧交通新纪元:AI赋能下的交通治理革命与技术演进路径
  • 北京大学肖臻老师《区块链技术与应用》公开课:04-BTC-共识协议
  • 【n-grams】基于统计方法的语言模型
  • ⚡️ Linux 系统安装与配置 Git
  • webpack的安装
  • spring和Mybatis的各种查询
  • YOLO-UniOW概述 论文
  • 华为OD最新机试真题-反转每对括号间的子串-OD统一考试(B卷)
  • 小猴子摆玩具
  • python--=的用法
  • 用python制作一个打地鼠游戏
  • Condition源码解读(二)
  • 基于物理约束的稀疏IMU运动捕捉系统
  • Spring AI 集成多个大语言模型
  • canal高可用配置
  • Linux中的Shell脚本基础
  • 惠州网站建设/百度拉新推广平台
  • 济南一哥网站建设公司/推广策略可以分为哪三种
  • 目前国内家教做的好的网站/软文平台
  • 怎么建设一个电影网站/今日腾讯新闻最新消息
  • 山东鲁桥建设有限公司网站/品牌运营公司
  • 山东鲁中公路建设有限公司网站/百度推广怎么弄