排序,贪心,栈,树状数组,二分。
因为要在个数最多的情况下保证收益最多,所以任务和机器都按照$y$从小到大排序,然后看每一个机器去处理哪一个任务。肯定是在任务的$y$小于等于机器的$y$的任务中寻找一个$x$最大的,这样能保证个数最多的情况下保证收益最多。
#include<cstdio> #include<cstring> #include<cmath> #include<stack> #include<algorithm> #include<iostream> using namespace std; const int maxn=100010; int n,m; struct X { long long x,y; }s[maxn],t[maxn]; bool cmp(X a,X b) { return a.y<b.y; } stack<int>st[1500]; int c[1500]; int lowbit(int x) { return x&(-x); } int get(int p) { int res=0; while(p>0) { res=res+c[p]; p=p-lowbit(p); } return res; } void update(int p,int val) { while(p<=1440) { c[p]=c[p]+val; p=p+lowbit(p); } } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) scanf("%lld%lld",&s[i].x,&s[i].y); for(int i=1;i<=m;i++) scanf("%lld%lld",&t[i].x,&t[i].y); sort(s+1,s+1+n,cmp); sort(t+1,t+1+m,cmp); // for(int i=1;i<=m;i++) st[t[i].x].push(i); for(int i=1;i<=1450;i++) { while(!st[i].empty()) st[i].pop(); } memset(c,0,sizeof c); int ans1=0; long long ans2=0; int pre=1; for(int i=1;i<=n;i++) { while(1) { if(pre>m) break; if(t[pre].y<=s[i].y) { st[t[pre].x].push(pre); update(t[pre].x,1); pre++; } else break; } int L=1,R=s[i].x,pos=-1; while(L<=R) { int mid=(L+R)/2; if(get(s[i].x)-get(mid-1)) L=mid+1,pos=mid; else R=mid-1; } if(pos==-1) continue; ans1++; int id=st[pos].top(); st[pos].pop(); ans2=ans2+500*t[id].x+2*t[id].y; update(pos,-1); } printf("%d %lld ",ans1,ans2); } return 0; }