2016 acm香港网络赛 D.Curious Cupid[莫队算法]

题意:给你两串数,一串代表男的,一串代表女的,每个数代表这个人说的语言,现在要给一个区间[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]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值