BZOJ3203 SDOI2013 保护出题人 凸包+三分法

题意:给定N组询问和D,初始时集合为空,每组询问先向集合的开头插入一个元素xi,然后给出一个数pi,求最小的yi使得\[{y}_{i}\left({p}_{i}+D\left(i-1 \right) \right)\geq {x}_{i}\]

题解:设Si=$\sum\limits_{j = 1}^i{x}_{j}$,显然yi=$max\left \{ \frac{{S}_{i}-{S}_{j-1}}{x_{i}+D\left ( i-j \right )} \right \},1\leq j\leq i$,设$a_j=D\cdot j,b_j=S_{j-1}$,那么我们就是要求(ak,bk)使得其与$\left ( x_i+D\cdot i,S_i \right )$的连线斜率最小,显然这个点一定是在一个由(a,b)组成的凸包上,而且斜率的取值一定是一个单峰,三分即可

#include <cstdio>
#include <iomanip>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define eps 1e-7
#define ll long long
#define ld long double

const int MAXN=100000+2;
struct Point{
    ld x,y;
    Point(){}
    Point(ld _x,ld _y):x(_x),y(_y){}
}Sta[MAXN];
int N,Top;
ll D,S[MAXN],x;
ld Ans;

ld Calc(Point a,Point b){ return (b.y-a.y)/(b.x-a.x);}

void Insert(Point x){
    while(Top>=2 && Calc(Sta[Top-1],Sta[Top])>=Calc(Sta[Top],x)-eps) Top--;
    Sta[++Top]=x;
}

ld Find(Point x){
    ld lk,rk,Ret=-1;
    int l=1,r=Top,lm,rm;
    while(r-l>=3){
        lm=(l+l+r)/3,rm=(l+r+r)/3;
        lk=Calc(Sta[lm],x),rk=Calc(Sta[rm],x);
        if(lk>rk) r=rm;
        else l=lm;
    }

    for(int i=l;i<=r;i++) Ret=max(Ret,Calc(Sta[i],x));
    return Ret;
}

int main(){
    cin >> N >> D;
    for(int i=1;i<=N;i++){
        scanf("%lld %lld",S+i,&x),S[i]+=S[i-1];
        Insert(Point(i*D,S[i-1])),Ans+=Find(Point(i*D+x,S[i]));
    }
    cout << fixed << setprecision(0) << Ans << endl;

    return 0;
}

时间: 2024-10-20 21:16:49

BZOJ3203 SDOI2013 保护出题人 凸包+三分法的相关文章

bzoj3203: [Sdoi2013]保护出题人 凸包+三分

/************************************************************** Problem: 3203 User: wangyucheng Language: C++ Result: Accepted Time:344 ms Memory:4396 kb ****************************************************************/ #include<iostream> #include&l

【bzoj3203】[Sdoi2013]保护出题人 凸包+二分

题目描述 输入 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的僵尸,排头僵尸从距离房子Xi米处开始接近. 输出 一个数,n关植物攻击力的最小总和 ,保留到整数. 样例输入 5 2 3 3 1 1 10 8 4 8 2 3 样例输出 7 题解 凸包+二分 把第 $i$ 只僵尸的血量看作前 $i$ 只僵尸的血量的前缀和,那么就相当于所有僵尸同时受到伤害. 把僵尸的

[bzoj3203][Sdoi2013]保护出题人

人生第一道三分?... 把进攻序列里的前i只僵尸看成一个点,横坐标是第i只僵尸到达的时间,纵坐标是这i只僵尸的血量总和..就是说植物必须在这段时间内输出这些伤害..那么单位时间的输出伤害就是斜率了. 问题就变成了对于若干个点,求从原点到各个点斜率的最大值. 因为D是固定的,而每次新加入僵尸实际就是把原来的点平移..并且相对位置关系不变...所以显然斜率最大的点一定在凸包上= = 每次就新加入一个点并维护凸包,然后三分找出凸包上的点与原点连线斜率的最大值(原点与凸包上各个点连线的斜率是单峰的)就好

BZOJ 3203 Sdoi2013 保护出题人 凸包+三分

题目大意:太长自己看 令sumi表示第i个僵尸以及之前的僵尸的体力总和.disi表示第i个僵尸与房屋的初始距离 我们发现我们能消灭一个僵尸当且仅当y>=sumidisi 那么我们要求的显然就是max{sumidisi} 我们将一个僵尸抽象成一个点sumidisi.那么我们发现每一个回合僵尸之间的相对位置是不变的 因此我们能够维护一个凸包.三分就可以 #include <cstdio> #include <cstring> #include <iomanip> #i

BZLJ 3203 Luogu P3299 [SDOI2013]保护出题人 (凸包、斜率优化、二分)

惊了,我怎么这么菜啊.. 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=3203 (luogu)https://www.luogu.org/problemnew/show/P3299 题解: 先讲正常做法. 设\(S_i\)为\(i\)的前缀和,则显然第\(i\)次答案为\(\max^i_{j=1} \frac{S_i-S_{j-1}}{x_i+id-jd}\) 那么很显然就是要求从一个点\((x_i+id,S_i)\)

【BZOJ3203】[Sdoi2013]保护出题人 二分+凸包

[BZOJ3203][Sdoi2013]保护出题人 Description Input 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离.接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的僵尸,排头僵尸从距离房子Xi米处开始接近. Output 一个数,n关植物攻击力的最小总和 ,保留到整数. Sample Input 5 2 3 3 1 1 10 8 4 8 2 3 Sample Output 7 HINT 第

SDOI2013 保护出题人

Description ?出题人铭铭认为给SDOI2012 出题太可怕了,因为总要被骂,于是他又给SDOI2013 出题了. 参加SDOI2012 的小朋友们释放出大量的僵尸,企图攻击铭铭的家.而你作为SDOI2013的参赛者,你需要保护出题人铭铭. 僵尸从唯一一条笔直道路接近,你们需要在铭铭的房门前放置植物攻击僵尸,避免僵尸碰到房子.第一关,一只血量为a1 点的僵尸从距离房子x1 米处匀速接近,你们放置了攻击力为y1 点/秒的植物进行防御:第二关,在上一关基础上,僵尸队列排头增加一只血量为a2

bzoj-3203 保护出题人

题意: 在一个诡异的植物大战僵尸游戏中,给出n关: 第i关队首僵尸距房门xi,两个僵尸之间间隔为d: 每次在队首添加一个血量为ai的僵尸,其他僵尸不变: 每关在门前放一个攻击力任意的植物,求n关放置植物总攻击力的最小值: n<=100000,其他数据<=10^12: 题解: 题意叙述略诡异..建议还是去看一眼原题: 首先考虑对于每一关的答案,应该是恰好将最难打死的僵尸打死的攻击力值: 令s[i]为i这个僵尸血量与它前面僵尸血量之和,dis[i]为这个僵尸距房门的距离: 那么答案就是ans=ma

保护出题人「SDOI 2013」

题意 有n个关卡,每一关都会在僵尸队列的排头添加一只僵尸,同时排头与家的距离会发生变化.相邻僵尸之间的距离固定为\(d\). 对于每一关,可以放置一颗任意攻击力的植物(每颗植物仅作用于当前关卡).求攻击力总和最小值. 思路 显然\(f[i]=max(\frac{sum[i]-sum[j-1]}{x[i]+d*(i-j)})\),由于斜率没有单调性,所以二分凸包. 另注:题目的取整指的是四舍五入而不是向下取整,恶臭. 代码 #include <bits/stdc++.h> using names