知识点
容斥原理常常用于解决集合的计数问题。
例题
1 . 洛谷 P2692 覆盖
思路:分别统计男生扫的行与女生扫的列的总数,但是可能存在重复扫同一个格子的情况,通过容斥原理,减去重复计算的格子,从而计算出这些学生总共打扫了多少方格。又因为二维数组所需的空间特别大,用一维数组统计哪些行和列扫过,最后统计时直接加上当前行或列的格子数即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define re register
using namespace std;
int n,m,b,g;
int check_hang[5005],check_lie[5005];
inline int read()
{
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int main()
{
n=read(); m=read(); b=read(); g=read();
int sum=0,x,y;
for(int i=1;i<=b;++i)
{
x=read(); y=read();
for(int j=x;j<=y;++j)
{
check_hang[j]=1; //标记哪些行被扫过
}
}
for(int i=1;i<=g;++i)
{
x=read(); y=read();
for(int j=x;j<=y;++j)
{
check_lie[j]=1; //标记哪些列被扫过
}
}
for(int i=1;i<=n;++i)
{
if(check_hang[i]==1) sum+=m; //统计被扫过的行的格子数
}
for(int i=1;i<=m;++i)
{
if(check_lie[i]==1)
{
sum+=n; //统计被扫过的列的格子数
for(int j=1;j<=n;++j)
{
if(check_hang[j]==1) sum--; //减去重复扫的格子
}
}
}
printf("%d",sum);
return 0;
}