今日得分:100+36+100(^_^)
T1
题目大意:有n个敌人,每个敌人有一个生命值w和攻击力s,有A+B个队友,其中A个每次能消灭一个生命值<xi的敌人,B个每次能消灭一个攻击力<yi的敌人,每人每次只能消灭一个敌人,问最少多少次能把所有敌人消灭,无解输出-1。n<=5e5,A,B<=5e4,1<=x,y,w,s<=2e9。
题解:二分答案,将敌人按照w排序,问题转化为判断一个答案是否合法。从大到小看w,每次把xj>wi的Aj找出,计算总共找出的A能不能消灭当前的敌人。如果不能消灭,则找到当前需要使用A来消灭的敌人中s最小的一个,用最小的能消灭它的B消灭它,如果找不到这样的B则不合法。使用二分,线段树,堆等即可维护上述操作。时间复杂度O(nlog^2n)
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
inline int re_ad()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+(ch^48),ch=getchar();
return x*f;
}
int A,B,n;
int a[50010],b[50010];
struct node{int a,b;}c[500010];
inline int mi(int x,int y){return x>y?y:x;}
bool cmp1(node x,node y){if(x.a!=y.a)return x.a<y.a;return x.b>y.b;}
long long t[200010];
void build(int k,int l,int r,int nu)
{
if(l==r){t[k]=nu;return;}
int mid=(l+r)>>1;build(k<<1,l,mid,nu);build(k<<1|1,mid+1,r,nu);
t[k]=t[k<<1]+t[k<<1|1];
}
bool change(int k,int l,int r,int L,int R)
{
if(!t[k])return false;
if(l==r){--t[k];return true;}
int mid=(l+r)>>1;
bool ret=false;
if(R<=mid){if(change(k<<1,l,mid,L,R)){ret=true;}}
else if(L>mid)ret=change(k<<1|1,mid+1,r,L,R);
else
{
if(change(k<<1,l,mid,L,R))ret=true;
else ret=change(k<<1|1,mid+1,