其实当时就觉得很像奶酪这道题,但思维固执了,就再也没往下想了

首先很清晰的二分答案

再就考虑check函数怎么维护了,

结合奶酪那道题,也用并查集维护

上界和下界分别当做一个限制点

如何判断二分的答案能否走过去

只要上界与下界不在同一个集合就可

code by hs

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 510
#define eps 1e-6
template<typename T>T read()
{
    T res=0;
    int sym=1;
    char cc=getchar();
    while(!isdigit(cc)&&cc!='-')cc=getchar();
    if(cc=='-')sym=-1,cc=getchar();
    while(!isdigit(cc))cc=getchar();
    while(isdigit(cc))res=res*10+cc-'0',cc=getchar();
    return res*sym;
}
template<typename T>void read(T &o)
{
    o=read<T>();
}
template<typename T,typename... Other>void read(T& a,Other&... b)
{
    a=read<T>();
    read(b...);
}
int n,L,x[maxn],y[maxn],fa[maxn];
int find(int x)
{
    return fa[x]==x? x:fa[x]=find(fa[x]);
}
bool check(double o)
{
    for(int i=1;i<=n+2;i++)
        fa[i]=i;
    for(int i=1;i<=n;i++)
    {
        if(y[i]-o<-eps)
            fa[find(i)]=find(n+1);
        if(y[i]+o>L+eps)
            fa[find(i)]=find(n+2);
        if(find(n+1)==find(n+2))
            return false;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])<o*o-eps)
            {
                fa[find(i)]=find(j);
            }
            if(find(n+1)==find(n+2))
                return false;
        }
    }
    return find(n+1)!=find(n+2);
}
int main()
{
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    read(n,L);
    for(int i=1;i<=n;i++)
        read(x[i],y[i]);
    double l=0,r=L;
    for(int i=1;i<=30;i++)
    {
        double mid=(l+r)/2;
        if(check(mid))l=mid;
        else r=mid;
    }
    printf("%.3lf\n",(l+r)/2);
    return 0;
}

反正我坚信我是对的

code by wzxbeliever

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) x&(-x)
#define il inline
#define ri register int
using namespace std;
const int maxn=5e4+5;
int T,n;
int a[maxn],vis[maxn];
struct node{
    int id,val;
    bool friend operator <(node a,node b){return a.val<b.val;}
}tmp;
priority_queue<node>Q;
int main(){
    //freopen("A.in","r",stdin);
//  freopen("A.out","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        ll sum=0;int num=0;memset(vis,0,sizeof(vis));
        while(!Q.empty())Q.pop();
        for(ri i=1,x;i<=n;i++){scanf("%d",&x);
        tmp.id=i,tmp.val=-x;
        Q.push(tmp),Q.push(tmp);
        ll t=x+Q.top().val;
        vis[Q.top().id]++;
        //cout<<"t="<<t<<endl;
        sum+=t;
        Q.pop();
        }
    //  while(!Q.empty())printf("%d ",Q.top().val),Q.pop();
        for(ri i=1;i<=n;i++)if(vis[i]==2)num++;num<<=1;
        cout<<sum<<" "<<num<<endl;
    }
    return 0;
}
/*
2
3
1 2 3
3
3 2 1
*/

维护一个小根堆,每次加入元素两次,如果最后该元素被弹出了两次,则它一定是买的

02-12 22:35