写此题时并不会multiset,就写了个树状数组
先把100,000,000的数据离散化了,最多就对映到1-200,000(理由见数据范围
开权值树状数组,即1-200,000的范围
排序后贪心思路是一样的,查询第1个大于等于是什么数时就二分
初始区间为
左端点:当前奶牛花钱最小值
右端点:N+M
树状数组查询区间是否有数(即区间和),有数就缩小右端点(区间和不为零),否则增大左端点
无解情况就是有一头奶牛初始区间和为0
不过multiset,确实方便许一些,而且快得多
二维偏序思想:先保证一维有序
#include<iostream> #include<cstdio> #define ri register int #define u long long namespace opt { inline u in() { u x(0),f(1); char s(getchar()); while(s<'0'||s>'9') { if(s=='-') f=-1; s=getchar(); } while(s>='0'&&s<='9') { x=(x<<1)+(x<<3)+s-'0'; s=getchar(); } return x*f; } } using opt::in; #define NN 200005 #include<algorithm> namespace mainstay { u N,M,ans(0),now(1),t[NN],cnt,len,pre[NN],w[NN<<1]; struct node { u x,y; } a[NN],b[NN]; void add(const u &x,const u &y) { for(ri i(x); i<=N+M; i+=i&-i) t[i]+=y; } u ask(const u &x) { u _re(0); for(ri i(x); i>=1; i-=i&-i) _re+=t[i]; return _re; } inline bool cmp(const node &x,const node &y) { return x.y>y.y; } void li_sanhua() { cnt=0; for(ri i(1); i<=N; ++i) w[++cnt]=a[i].x; for(ri i(1); i<=M; ++i) w[++cnt]=b[i].x; std::sort(w+1,w+cnt+1),len=std::unique(w+1,w+cnt+1)-w-1; for(ri i(1); i<=N; ++i) pre[std::lower_bound(w+1,w+len+1,a[i].x)-w]=a[i].x; for(ri i(1); i<=M; ++i) pre[std::lower_bound(w+1,w+len+1,b[i].x)-w]=b[i].x; for(ri i(1); i<=N; ++i) a[i].x=std::lower_bound(w+1,w+len+1,a[i].x)-w; for(ri i(1); i<=M; ++i) b[i].x=std::lower_bound(w+1,w+len+1,b[i].x)-w; cnt=0; for(ri i(1); i<=N; ++i) w[++cnt]=a[i].y; for(ri i(1); i<=M; ++i) w[++cnt]=b[i].y; std::sort(w+1,w+cnt+1),len=std::unique(w+1,w+cnt+1)-w-1; for(ri i(1); i<=N; ++i) a[i].y=std::lower_bound(w+1,w+len+1,a[i].y)-w; for(ri i(1); i<=M; ++i) b[i].y=std::lower_bound(w+1,w+len+1,b[i].y)-w; } inline void solve() { N=in(),M=in(); for(ri i(1); i<=N; ++i) a[i].x=in(),a[i].y=in(); for(ri i(1); i<=M; ++i) b[i].x=in(),b[i].y=in(); li_sanhua(),std::sort(a+1,a+N+1,cmp),std::sort(b+1,b+M+1,cmp); for(ri i(1); i<=N; ++i) { while(b[now].y>=a[i].y) add(b[now].x,1),++now; u _re,_l(a[i].x),_r(N+M); if(!(ask(_r)-ask(_l-1))) { printf("-1"); return; } while(_l<=_r) { u mid(_l+_r>>1); if((ask(mid)-ask(_l-1))>0) _r=mid-1,_re=mid; else _l=mid+1; } ans+=pre[_re],add(_re,-1); } std::cout<<ans; } } int main() { //freopen("food.in","r",stdin); //freopen("food.out","w",stdout); std::ios::sync_with_stdio(false); mainstay::solve(); }
转自本人自己的luogu博客。