题解 P5149 【会议座位】
实际发表时间:2020-04-22
https://www.luogu.com.cn/problem/P5149
不难发现,此题就是在找逆序对,只不过数字换成了字符串
注:方法2不是重复的解法
我用归并排序来求数字的逆序对
那么字符串怎么找逆序对呢?
方法1:\(map\)
基本上其他题解也都有用,设一个\(map<string,int>m\)即可,映射的数字是字符串的编号。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
string s;
int n,a[N],b[N];
long long ans;//记得开longlong
map<string,int>m;//map在这里
void merge_sort(int left,int right)//归并排序
{
if(left>=right) return;
int mid = (right-left)/2+left;
merge_sort(left,mid);
merge_sort(mid+1,right);
int i=left,j=mid+1,k=left;
while(i<=mid && j<=right)
{
if(a[i]<a[j]) b[k++]=a[i++];
else b[k++] = a[j++],ans+=mid-i+1;//增加逆序对
}
while(i<=mid) b[k++] = a[i++];
while(j<=right) b[k++] = a[j++];
for(int i=left;i<=right;i++) a[i]=b[i];
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);//加速cincout
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s;
m[s]=i;//当前编号
}
for(int i=1;i<=n;i++)
{
cin>>s;
a[m[s]]=i;
}
merge_sort(1,n);
cout<<ans;
return 0;
}
方法2:字符串排序
发现其他题解都没有这个做法,我来一个吧。
我们可以写一个结构体,保存原来和现在的两个字符串,然后以原来的字符串为关键字进行排序,接着就可以字符串式归并排序。
而且\(string\)的运算符已经被重载,直接使用归并排序即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
string a[N],b[N];
int n;
long long ans;/longlong!
struct node
{
string s,a;//原来的s和现在的a
}s[N];
void merge_sort(int left,int right)//归并排序
{
if(left>=right) return;
int mid = (right-left)/2+left;
merge_sort(left,mid);
merge_sort(mid+1,right);
int i=left,j=mid+1,k=left;
while(i<=mid && j<=right)
{
if(a[i]<a[j]) b[k++]=a[i++];
else b[k++] = a[j++],ans+=mid-i+1;
}
while(i<=mid) b[k++] = a[i++];
while(j<=right) b[k++] = a[j++];
for(int i=left;i<=right;i++) a[i]=b[i];
}
bool cmp(node x,node y)
{
return x.s<y.s;//以原来为关键字
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);//加速
cin>>n;
for(int i=1;i<=n;i++)cin>>s[i].s;
for(int i=1;i<=n;i++)cin>>s[i].a;
sort(s+1,s+n+1,cmp);//sort排序
for(int i=1;i<=n;i++)a[i]=s[i].a;//现在的赋值给a数组,可直接套到归并排序
merge_sort(1,n);
cout<<ans;
return 0;
}
记得开\(\mathcal{LONG\;LONG}\)!
做法新颖,求过

浙公网安备 33010602011771号