题意:
有若干个区间,若干种数,每个数告诉你有多少个。
然后一个数可以被放到一个x∈该区间 的区间,问最多有多少个区间可以被放。
题解:
显然我们可以用二分图最大匹配做,水题。
但是此题有别的技巧、
就是我们可以贪心进行处理。
首先我们考虑到需要将两种数都排个序。
然后再进行贪心。
一种错误的贪心法是单调队列式贪心,就是记录个top,然后单调往后推。
这个不仔细想还不知道它是错的。
额,至于卡它的数据,,我可以提供给你一个错误代码和一个拍子,你们可以自己拍一组数据出来,很高效。
这里贴一份错误代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 3000 #define inf 0x3f3f3f3f using namespace std; int n,m,ans,i; struct KSD { int x,y; bool operator < (const KSD &a)const{return x==a.x?(y<a.y):(x<a.x);} }cow[N],oil[N]; int main() { // freopen("test.in","r",stdin); scanf("%d%d,",&n,&m); for(i=1;i<=n;i++)scanf("%d%d",&cow[i].x,&cow[i].y); for(i=1;i<=m;i++)scanf("%d%d",&oil[i].x,&oil[i].y); sort(cow+1,cow+n+1); sort(oil+1,oil+m+1); int top=1; for(i=1;i<=m;i++) { while(top<=n&&cow[top].y<oil[i].x)top++; while(top<=n&&oil[i].y&&cow[top].x<=oil[i].x) { if(oil[i].x<=cow[top].y) { oil[i].y--; ans++; } top++; } } printf("%d\n",ans); return 0; }
这里贴一份数据生成器
#include <ctime> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 10 #define inf 0x3f3f3f3f using namespace std; int n,m; int main() { srand((unsigned)time(NULL)); int i,j,k; int a,b,c; n=rand()%N+1; m=rand()%4+1; printf("%d %d\n",n,m); for(i=1;i<=n;i++) { a=rand()%N+1; b=rand()%N+a; printf("%d %d\n",a,b); } for(i=1;i<=m;i++) { a=rand()%(N*2)+1; b=rand()%3+1; printf("%d %d\n",a,b); } return 0; }
这里贴个拍子
#include <ctime> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define N 3000 using namespace std; int main() { int i,g; system("g++ std.cpp -o std -g"); system("g++ my.cpp -o my -g"); system("g++ rand.cpp -o rand -g"); for(g=1;g<=N;g++) { printf("Case %d : ",g); system("rand>test.in"); clock_t j=clock(); system("my <test.in >my.out"); clock_t k=clock(); printf("my_use : %03dms ",k-j); system("std <test.in >std.out"); printf("std_use : %03dms ",clock()-k); if(system("fc std.out my.out >NULL")==0){puts("result : AC");} else { puts("WAWAWAWAWAWAWAWA!!!!!!!!"); system("start test.in"); return 0; } } puts(""); puts("****,please try again"); return 0; }
拿上述的东西,再找个标程就可以pai了。
下面说一下正确思路。
首先按照顺序我们可以知道哪些区间的下界满足条件,那么就只需要上界也满足条件就行了。
因为数递增,所以如果当前的某个可用区间的上界比当前数小,那么以后也不可能满足了,就可以弹出去。
这样通过优先队列可以得到一个上界满足且最小的区间,这个区间则可以被计入答案。
思想说了个大概,没懂就看代码吧。
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 3000 #define inf 0x3f3f3f3f using namespace std; int n,m,ans,i; priority_queue<int>pq; struct KSD { int x,y; bool operator < (const KSD &a)const{return x==a.x?(y<a.y):(x<a.x);} }cow[N],oil[N]; int main() { // freopen("test.in","r",stdin); scanf("%d%d,",&n,&m); for(i=1;i<=n;i++)scanf("%d%d",&cow[i].x,&cow[i].y); for(i=1;i<=m;i++)scanf("%d%d",&oil[i].x,&oil[i].y); sort(cow+1,cow+n+1); sort(oil+1,oil+m+1); int top=1; for(i=1;i<=m;i++) { while(top<=n&&cow[top].x<=oil[i].x) pq.push(-1*cow[top++].y); while(!pq.empty()&&oil[i].y) { int ttt=pq.top(); if((-1*ttt)>=oil[i].x)ans++,oil[i].y--; pq.pop(); } } printf("%d\n",ans); return 0; }