题意:给你两串数,一串代表男的,一串代表女的,每个数代表这个人说的语言,现在要给一个区间[L,R]里面的人配对,只有语言相同的才能配一对,问对于每个区间,最多能配成几对。
思路:莫队算法来处理。
#include<bits/stdc++.h>
using namespace std;
//#define min(a,b) a>=b?b:a
struct lx{
int l,r,id;
}p[50005];
int n,m,k,sq;
bool cmp(lx a,lx b){
if(a.l/sq==b.l/sq)return a.r<b.r;
else return a.l/sq<b.l/sq;
}
int ed1[50005],ed2[50005];
int ans[50005];
int mp1[1000005],mp2[1000005];
void work(){
int left=0,right=-1;
int cnt=0;
for(int i=0;i<m;++i){
while(right<p[i].r){
right++;
cnt-=min(mp1[ed1[right]],mp2[ed1[right]]);
if(ed2[right]!=ed1[right])cnt-=min(mp1[ed2[right]],mp2[ed2[right]]);
mp1[ed1[right]]++;
mp2[ed2[right]]++;
cnt+=min(mp1[ed1[right]],mp2[ed1[right]]);
if(ed2[right]!=ed1[right])cnt+=min(mp1[ed2[right]],mp2[ed2[right]]);
}
while(right>p[i].r){
cnt-=min(mp1[ed1[right]],mp2[ed1[right]]);
mp1[ed1[right]]--;
if(ed2[right]!=ed1[right])cnt-=min(mp1[ed2[right]],mp2[ed2[right]]);
mp2[ed2[right]]--;
cnt+=min(mp1[ed1[right]],mp2[ed1[right]]);
if(ed2[right]!=ed1[right])cnt+=min(mp1[ed2[right]],mp2[ed2[right]]);
right--;
}
while(left>p[i].l){
left--;
cnt-=min(mp1[ed1[left]],mp2[ed1[left]]);
mp1[ed1[left]]++;
if(ed2[left]!=ed1[left])cnt-=min(mp1[ed2[left]],mp2[ed2[left]]);
mp2[ed2[left]]++;
cnt+=min(mp1[ed1[left]],mp2[ed1[left]]);
if(ed2[left]!=ed1[left])cnt+=min(mp1[ed2[left]],mp2[ed2[left]]);
}
while(left<p[i].l){
cnt-=min(mp1[ed1[left]],mp2[ed1[left]]);
mp1[ed1[left]]--;
if(ed2[left]!=ed1[left])cnt-=min(mp1[ed2[left]],mp2[ed2[left]]);
mp2[ed2[left]]--;
cnt+=min(mp1[ed1[left]],mp2[ed1[left]]);
if(ed2[left]!=ed1[left])cnt+=min(mp1[ed2[left]],mp2[ed2[left]]);
left++;
}
ans[p[i].id]=cnt;
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
sq=(int)sqrt(m);
for(int i=0;i<n;++i){
scanf("%d",&ed1[i]);
}
for(int i=0;i<n;++i){
scanf("%d",&ed2[i]);
}
for(int i=0;i<m;++i){
scanf("%d%d",&p[i].l,&p[i].r);
p[i].id=i;
}
sort(p,p+m,cmp);
work();
for(int i=0;i<m;++i){
printf("%d\n",ans[i]);
}
}