ABC 314 GH 题解

没打,花了 10 分钟跟 piggy 用 qq 胡的做法:

G - Amulets

很明显的扫描线。

打到的怪物的编号是单调不减的,尝试增加怪物时平衡树找到 $B_i$ 的和最大的 $K$ 种颜色的 $B_i$ 的和,判断是否可以打败总伤害减去这个值即可。平衡树用 multiset 即可。

具体的:增加点的时候,如果在前 $K$ 个,加上自己的权值然后减一个权值,大于 $K$ 不变。第 $K$ 个值用一个指针保存。

$O(n \log m)$

部分代码:

void erase(ll x){
    auto i=s1.find(x);
    if(i!=s1.end())s1.erase(i),sum-=x,r--;
    else s2.erase(s2.find(x));
}
void insert(ll x){
    if(s1.size()){
        auto i=s1.end();i--;
        if(x>*i){
            s1.insert(x),sum+=x,r++;
            return;
        }
    }
    s2.insert(x);
}
signed main(){
    n=read(),m=read(),h=read();
    rep(i,1,m)s2.insert(0);
    r=0;
    rep(i,1,n){
        a[i]=read(),b[i]=read();
        al+=a[i];
        erase(c[b[i]]);
        c[b[i]]+=a[i];
        insert(c[b[i]]);
        while(al-sum<h&&r){
            auto it=s1.end();it--;
            if(al-sum+*it>=h)break;
            sum-=*it;
            s2.insert(*it);
            s1.erase(it);
            r--;
        }
        while(al-sum>=h){
            sum+=*s2.begin();
            s1.insert(*s2.begin());
            s2.erase(s2.begin());
            r++;
        }
        p[i]=r;
    }
    rep(i,0,m)printf("%lld ",upper_bound(p+1,p+n+1,i)-p-1);
    return 0;
}

Ex - Disk and Segments

题意就是找到距离 $n$ 条线段最近的一个点,模拟退火。

跟 P1337 类似,改改即可,感觉很板。

代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
inline double Rand(){
    return (double)rand()/RAND_MAX;
}
struct node{
    double x,y;
    void in(){scanf("%lf%lf",&x,&y);}
}a[103],b[103];
node operator-(node x,node y){return {x.x-y.x,x.y-y.y};}
double len(node x){return sqrt(x.x*x.x+x.y*x.y);}
int dcmp(double x){return fabs(x)<1e-10?0:x<0?-1:1;}
double dot(node x,node y){return x.x*y.x+x.y*y.y;}
double cross(node x,node y){return x.x*y.y-x.y*y.x;}
double distoseg(node p,node a,node b){
    node x=b-a,y=p-a,z=p-b;
    if(dcmp(dot(x,y))<0)return len(y);
    if(dcmp(dot(x,z))>0)return len(z);
    return fabs(cross(x,y)/len(x));
}
int n;
double t,mn,sx,sy;
double get(double x,double y){
    double ans=0;
    rep(i,1,n)ans=max(ans,distoseg({x,y},a[i],b[i]));
    if(ans<mn)mn=ans,sx=x,sy=y;
    return ans;
}
signed main(){
    srand((unsigned long long)new char);
    scanf("%d",&n);
    rep(i,1,n){
        a[i].in(),b[i].in();
        sx+=(a[i].x+b[i].x)/2.0,sy+=(a[i].y+b[i].y)/2.0;
    }
    sx/=n,sy/=n,mn=get(sx,sy);
    t=1e3;
    double nx=sx,ny=sy;
    while(t>0.000001){
        double x=nx+t*(Rand()*2-1),y=ny+t*(Rand()*2-1);
        if(exp((get(nx,ny)-get(x,y))/t)>Rand())nx=x,ny=y;
        t*=0.99995;
    }
    rep(i,1,100000){
        double x=sx+t*(Rand()*2-1),y=sy+t*(Rand()*2-1);
        get(x,y);
    }
    printf("%.8lf",mn);
    return 0;
}
posted @ 2023-08-12 22:38  zifanwang  阅读(6)  评论(0编辑  收藏  举报  来源