题目链接:https://ac.nowcoder.com/acm/contest/1083/D
题意
有一个草原可以用一个1~400的数轴表示。有n头羊和q个查询。每头羊的编号分别是1,2,3…n。第i头羊只喜爱数轴上[ai,bi]这样的一个闭区间,每一时刻每头羊只可能在自己喜爱的区间的某个点上吃草。现在给出q个查询,每个查询两个整数l,r。你需要计算出在同一时刻,最多能有多少头羊同时在这个区间内吃草。数轴上每一个整点同一时刻只能容纳一只羊,羊只会在整点吃草。
输入描述
第一行三个数n q。
第二行n个数a1 a2…an。
第三行n个数b1 b2…bn。
接下来q行每行两个数l,r。表示询问的区间。
输出描述
对于每个查询,输出一个整数表示答案。
输入
5 3
1 1 1 2 4
1 1 1 3 5
1 5
2 5
1 3
输出
3
2
2
题解
因为每个位置只能被其中一只羊占据,所以可以将羊和位置分别看成二分图的两部分,将位置与羊匹配,如何建图?每只羊能占据的区间是给出,我们只需要将该区间的每一点连向羊,查询的时候从 l 到 r 跑一遍最大匹配即可,所以总复杂度为O(n^3)。
#include<bits/stdc++.h>
using namespace std;
#define maxn 405
#define ll long long
#define inf 1000000009
#define IOS ios::sync_with_stdio(false)
struct edge
{
int next,to;
}love[maxn*maxn];
int head[maxn],num;
void add(int from,int to)
{
love[++num].next=head[from];
love[num].to=to;
head[from]=num;
}
int n;//n为男孩最大值
int used[maxn], girl[maxn];//这两个数组的大小应为girl的最大值
vector<int>V;//避免对used每次memset的优化
bool find(int x)
{
for (register int j = head[x]; j; j = love[j].next) //扫描每个妹子
{
int v = love[j].to;
if (used[v] == false)
//如果有暧昧并且还没有标记过(这里标记的意思是这次查找曾试图改变过该妹子的归属问题,
//但是没有成功,所以就不用瞎费工夫了)
{
used[v] = 1;
V.push_back(v);
if (girl[v] == 0 || find(girl[v]))
{
//名花无主或者能腾出个位置来,这里使用递归
girl[v] = x;
return true;
}
}
}
return false;
}
int Hungary(int x,int y)
{
int all = 0;
memset(used,0,sizeof(used));
memset(girl,0,sizeof(girl));
for (int i = x; i <= y; i++)
{
if (find(i))
all += 1;
for (int i = 0; i<V.size(); i++)
used[V[i]] = false;
V.clear();
}
return all;
}
int L[maxn],R[maxn];
int main()
{
IOS;
int q;
cin>>n>>q;
for(int i=1;i<=n;i++)
cin>>L[i];
for(int i=1;i<=n;i++)
cin>>R[i];
for(int i=1;i<=n;i++)
for(int j=L[i];j<=R[i];j++)
add(j,i);
while(q--)
{
int x,y;
cin>>x>>y;
cout<<Hungary(x,y)<<"\n";
}
return 0;
}