测试。。。
移动到中位数位置能保证总移动距离最小,数学知识
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
int n;
string s;
cin >> n >> s;
vector<int> positions;
// 记录所有'1'的位置
for (int i = 0; i < n; ++i) {
if (s[i] == '1') {
positions.push_back(i);
}
}
int mid = positions.size() / 2;
long long ans = 0;
// 计算最少交换次数
for (int i = 0; i < positions.size(); ++i) {
ans += abs(positions[mid] - positions[i]) - abs(mid - i);
}
cout << ans << endl;
return 0;
}
abs(positions[mid] - positions[i]) 的含义
◦ 实际例子:假设这群人站在位置 1、3、5,mid = 1(因为有 3 个人,中间位置索引为 1,对应位置 3)。对于站在位置 1(即 i = 0,positions[0] = 1)的人,abs(positions[mid] - positions[0]) = abs(3 - 1) = 2。
◦ 含义解释:这表示这个人要移动到中间位置(位置 3),如果不考虑其他人,单纯看他自己移动到目标位置,通过相邻两人交换位置的方式,最少需要交换 2 次。在字符串中,就是这个 1要移动到所有 1 集中位置的中位数位置,需要的最少相邻字符交换次数。
#include<stdio.h>
int a[200003][200003],n,m,cnt=0;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d %d",&x,&y);
if(x==y||a[x][y]>0) cnt++;
else {
a[x][y]++;
a[y][x]++;
}
}
printf("%d\n",cnt);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int ans;
map<pair<int,int>,int>a;
int main() {
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int l,r;
cin>>l>>r;
if(a[{l,r}]==1||l==r)ans++;
else a[{l,r}]=1,a[{r,l}]=1;
}
cout<<ans;
}
在第一段代码中,定义了二维数组 a[200003][200003]。当 N 和 M 达到题目给定的上限(N 最大为 2×10^5,M 最大为 5×10^5)时,这个数组的内存需求极大,很可能会导致栈溢出错误。因为程序的栈空间是有限的,如此大的数组分配在栈上会超出栈的容量。
◦ 正确做法:应该使用更节省内存的方式来存储图的边信息,例如使用哈希表(如第二段代码中使用 map)或者邻接表结构。
map
基于红黑树实现,它以节点的形式存储数据。每个节点包含键值对以及指向其他节点的指针等信息。这种节点式的存储结构使得 map
在存储大量数据时,能够以一种较为紧凑和高效的方式利用内存。它不像二维数组那样需要连续的大量内存空间,而是可以在内存中分散存储,通过指针来建立节点之间的联系,提高了内存的使用效率,降低了超限的风险。
元素个数限制相对宽松:map 对存储元素的个数没有像静态数组那样严格的固定上限限制。只要系统还有可用的内存空间,map 就可以继续插入新的元素。当然,系统的内存也是有限的,但在一般情况下,对于题目中给定的输入规模(1≤N≤2×10^5,0≤M≤5×10^5),map 能够轻松应对,不会因为元素个数而轻易达到系统内存的极限。
#include<iostream>
#include<string>
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
string s;
cin>>n;
int t;
while(n--){
cin>>s;
t=s.size();
for(int i=0;i<t-1;i++){
if(s[i]==s[i+1]) t=1;
}
cout<<t<<endl;
}
return 0;
}
#include<iostream>
using namespace std;
const int N=2e5+3;
int a[N],b;
int main()
{
int t,n,m;
a[0]=-0x3f3f3f3;
cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>b;
int z=1;
for(int i=1;i<=n;i++){
int t=b-a[i];
if(t>=a[i-1]&&a[i]>=a[i-1]){
a[i]=min(a[i],t);
}
if(t>=a[i-1]&&a[i]<a[i-1]) a[i]=t;
if(a[i]<a[i-1]){
z=0;
break;
}
}
if(z) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
因为序列递增,将符合条件的a[i]/b-a[i]设置尽可能小,那么只要a[i]<a[i-1]输出no
#include<iostream>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int a,b;
cin>>a>>b;
if(b-a==1||(a-b+1)%9==0&&a>b) cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}