Kattis:Curious Cupid

Kattis:Curious Cupid

题目链接:https://open.kattis.com/problems/cupid

题目大意:有$n$个男生及$n$个女生,每人懂得$1$种语言(共$k$种语言),若男生懂的语言与女生相同即可配对(一人仅可配对一次)。现有$m$个区间,问各个区间内最大的配对人数。

莫队算法

$k$的数量级为$10^6$而$m$的数量级为$10^4$,故对于每个$m$去遍历$k$是行不通的。

考虑用莫队算法,先将所有区间按$lfloorfrac{L}{sqrt{n}} floor$升序$R$升序排序。

然后用数组lang[i][2]记录区间内男生女生懂语言$i$的人数,从第一个区间开始向下一个区间转移。

总复杂度为$O(n imes sqrt{n})$.

/*每次转移以函数,代码量少且清晰;ans数组代替了重新对q数组的排序*/

代码如下:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cmath>
 4 #define N 50005
 5 #define M 50005
 6 #define K 1000005
 7 using namespace std;
 8 int n,m,k,a[N][2],B,ans[M],lang[K][2];
 9 struct node{
10     int l,r,id;
11     bool operator<(const node x)const{
12         if(l/B==x.l/B)return r<x.r;
13         else return l/B<x.l/B;
14     }
15 }q[M];
16 void des(int p,int &ans){
17     int x=a[p][0],y=a[p][1];
18     if(lang[x][0]<=lang[x][1])ans--;
19     lang[x][0]--;
20     if(lang[y][1]<=lang[y][0])ans--;
21     lang[y][1]--;
22 }
23 void add(int p,int &ans){
24     int x=a[p][0],y=a[p][1];
25     if(lang[x][0]<lang[x][1])ans++;
26     lang[x][0]++;
27     if(lang[y][1]<lang[y][0])ans++;
28     lang[y][1]++;
29 }
30 int main(void){
31     std::ios::sync_with_stdio(false);
32     cin>>n>>m>>k;
33     B=sqrt(n);
34     for(int i=0;i<n;++i)cin>>a[i][0];
35     for(int i=0;i<n;++i)cin>>a[i][1];
36     for(int i=0;i<m;++i){
37         cin>>q[i].l>>q[i].r;
38         q[i].id=i;
39     }
40     sort(q,q+m);
41     int l=q[0].l,r=q[0].r,tmp=0;
42     for(int i=l;i<=r;++i)
43         lang[a[i][0]][0]++,lang[a[i][1]][1]++;
44     for(int i=0;i<k;++i)
45         tmp+=(lang[i][0]<lang[i][1]?lang[i][0]:lang[i][1]);
46     ans[q[0].id]=tmp;
47     for(int i=1;i<m;++i){
48         while(l<q[i].l){des(l,tmp);l++;}
49         while(l>q[i].l){l--;add(l,tmp);}
50         while(r<q[i].r){r++;add(r,tmp);}
51         while(r>q[i].r){des(r,tmp);r--;}
52         ans[q[i].id]=tmp;
53     }
54     for(int i=0;i<m;++i)
55         cout<<ans[i]<<"
";
56 }
原文地址:https://www.cnblogs.com/barrier/p/6444897.html