https://codeforces.com/contest/1132/problem/C
采用逆向思维,要求最大的覆盖,就先求出总的覆盖,然后减去删除两个人贡献最少的人
#include<iostream> #include<vector> #include<algorithm> using namespace std; vector<int> p[5002]; int con2[5002][5002],con1[5002];//一维数组:这个人的贡献,二维数组:这两个人共同的贡献 int main(){ int n,q; cin>>n>>q; int a,b; for(int i=1;i<=q;i++){ cin>>a>>b; for(int j=a;j<=b;j++){ p[j].push_back(i);//记录覆盖这个点的人 } } int total=0; for(int i=1;i<=n;i++){ int m=p[i].size(); if(m) total++;//算出覆盖的总数 if(m==1){//当前的点只有一个人覆盖的话,就算这个人的贡献 con1[p[i][0]]++; } else if(m==2){//有两个人覆盖的话,就算两个人的共同的贡献 con2[p[i][0]][p[i][1]]++; con2[p[i][1]][p[i][0]]++; }//如果有两个以上的话,就不算贡献了,因为及时删除两个人这个点还是被覆盖的 } int minn=INT_MAX; //遍历每两个点 for(int i=1;i<=q;i++){ for(int j=i+1;j<=q;j++){ minn=min(minn,con1[i]+con1[j]+con2[i][j]);//求出两个点的最小贡献 } } cout<<total-minn<<endl; return 0; }