【GDOI2017模拟8.14】守鹤之砂

4 篇文章 0 订阅
4 篇文章 0 订阅

Description

有n个数,执行n-1次合并。
每次合并两个数所在的集合并进行一次询问。
把这个合并后的集合里的数按照数轴上的顺序排序,你可以任意交换相邻的两个数,时间为他们之间的距离。
交换可以同时进行,一个数在进行交换时不能被选择。
当最小值和最大值进行交换时,时间为距离/2并且询问结束。
求最小时间。
n<=50000

Solution

首先,一次询问的答案是,对于相邻的两个数aj和aj+1,那么把a1换到aj,把an换到aj+1,再把他们两个交换是最优策略。
于是我们可以枚举j,Ans=min(max(aj-a1,an-aj+1)+(aj+1-aj)/2)
也就是min(max((aj+1-aj)/2-a1,an-(aj+1-aj)/2))
储存每两个数的中点,那么最接近a1,an中点的那个区间就是最优解。
这个也可以用二分实现。
至于合并,你可以写一个线段树合并,也可以用启发式合并两个set。(black technology)

Code

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 50005
using namespace std;
typedef double db;
typedef set<int> ::iterator it;
set<int> s[N];
int f[N],a[N],n,x,y,ty;
int get(int x) {return (f[x]-x)?f[x]=get(f[x]):x;}
bool cmp(int x,int y) {}
int merge(int x,int y) {
    int a=get(x),b=get(y);
    if (s[a].size()<s[b].size()) swap(a,b);
    for(it i=s[b].begin();i!=s[b].end();i++) s[a].insert(*i);f[b]=a;return a;
}
int main() {
    for(scanf("%d",&ty);ty;ty--) {
        scanf("%d",&n);
        fo(i,1,n) f[i]=i,s[i].clear(),s[i].insert(i);
        fo(i,1,n-1) {
            scanf("%d%d",&x,&y);
            int id=merge(x,y);it st=s[id].begin(),ed=s[id].end();ed--;
            it bz=s[id].lower_bound(ceil((*st+*ed)/2.0));
            int r=*bz;bz--;int l=*bz;
            db m=(l+r)/2.0;db ans=max(m-*st,*ed-m);
            l=r;bz++;bz++;r=*bz;
            if (bz!=s[id].end()) {
                m=(l+r)/2.0;
                ans=min(ans,max(m-*st,*ed-m));
            }
            bz--;bz--;r=*bz;bz--;l=*bz;
            if (r!=*st) {
                m=(l+r)/2.0;
                ans=min(ans,max(m-*st,*ed-m));
            }
            printf("%.1lf\n",ans);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值