「题解」:$d$

问题 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);
    }
}
View Code

ps.为数不多我这个蒟蒻在赛时写了对拍的题目。刚才发现它还在拍,拍了近两百万组了啊,纪念一下233。

「题解」:$d$_第1张图片

你可能感兴趣的:(「题解」:$d$)