问题 A: $d$
时间限制: 1 Sec 内存限制: 512 MB
题面
题面谢绝公开。
题解
赛时切掉了然而过程十分曲折。
贪心思路很好想。然而一开始错误以为是单峰。其实几个峰都有可能。
开场写了wqs二分,然后觉得不对最外围改成三分,大样例惨不忍睹,改写主席树A了。
扯远了。
正解贪心+堆。主席树也可以实现。我就按主席树的说了。
首先是贪心。去掉的m个一定是去掉了一些$ai$最小的,去掉了一些$bi$最小的。
所以考虑按照$ai$排序,枚举删掉前$i$个,对后面的做一个裸的kth-number就行了。

#include#define int long long #define rint register int using namespace std; const int N=100005; inline void read(int &A) { A=0;int B=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')B=-1;ch=getchar();} while(ch>='0'&&ch<='9'){A=(A<<3)+(A<<1)+ch-'0';ch=getchar();} A=A*B;return ; } int T,n,m,ans; struct node{int a,b;}mu[N]; int root[N],ls[N<<6],rs[N<<6],s[N<<6],sz; inline bool cmp(node A,node B){return A.a<B.a;} inline void insert(int x,int &y,int l,int r,int v) { y=++sz; s[y]=s[x]+1; if(l==r)return; ls[y]=ls[x];rs[y]=rs[x]; int mid=(l+r)>>1; if(v<=mid)insert(ls[x],ls[y],l,mid,v); else insert(rs[x],rs[y],mid+1,r,v); } inline int get_rank(int k,int l,int r,int x) { if(r==x)return s[k]; int mid=(l+r)>>1; if(x<=mid)return get_rank(ls[k],l,mid,x); else return s[ls[k]]+get_rank(rs[k],mid+1,r,x); } inline int ask(int L,int R,int v) { int x=root[L-1],y=root[R]; int l=1,r=N; while(l<=r) { int mid=(l+r)>>1; int t=get_rank(y,1,N,mid)-get_rank(x,1,N,mid); if(t>=v)r=mid-1; else l=mid+1; } return l; } signed main() { // freopen("1.in","r",stdin); // freopen("s1.out","w",stdout); read(T); while(T--) { ans=sz=0;read(n),read(m); for(rint i=1;i<=n;++i) read(mu[i].a),read(mu[i].b); sort(mu+1,mu+n+1,cmp); for(rint i=1;i<=n;++i) insert(root[i-1],root[i],1,N,mu[i].b); for(rint i=0;i<=m;++i) ans=max(ans,mu[i+1].a*ask(i+1,n,m-i+1)); printf("%lld\n",ans); } }
ps.为数不多我这个蒟蒻在赛时写了对拍的题目。刚才发现它还在拍,拍了近两百万组了啊,纪念一下233。