[BZOJ3203]-[Sdoi2013]保护出题人-凸包+三分
2017-12-05 21:34
363 查看
说在前面
第一次写三分,比想象的要艰辛啊…因为这道题是在搜索「三分」的时候发现的,于是直接就看到题解了…
不过看题解的时候快要困的睡着了…看半天半懂不懂的….
粗略推导了一下之后就开始写了,于是各种小bug= =
精神状态差的时候果然要拒绝写题!!!
题目
BZOJ3203传送门题面
懒得打字了=w=,直接粘图岂不美滋滋输入输出格式
输入格式:第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离。接下来n行每行两个空格隔开的正整数,第i + 1行为Ai和 Xi,分别表示相比上一关在僵尸队列排头增加血量为Ai 点的僵尸,排头僵尸从距离房子Xi米处开始接近。
输出格式:
一个数,n关植物攻击力的最小总和 ,保留到整数。
解法
由题意,前面的僵尸死了之后,后面的僵尸才能受到伤害,带着这样的时间限制是很难处理的。为了去掉这个限制,可以把后面僵尸的血量加上前面僵尸的血量总和,这样的处理与原题意等价这样问题就转化成了:有很多僵尸,它们从一开始就受到持续伤害,并且在到达房子之前死掉,询问这个持续伤害的最小值。很明显答案为:ans[i]=max(血量距离)=max(sum[i]−sum[j−1]x[i]+i∗d−j∗d),sum数组表示血量前缀和
但是N规模1e5,直接枚举肯定T的稳稳的
这时候就要靠智商思维了。注意到sum[i]−sum[j−1]x[i]+i∗d−j∗d与斜率形式很相似,我们把( x[i]+i∗d,sum[i] )作为P点,而(sum[j−1],j∗d)作为Qj点,那么答案就是P点到所有Qj点斜率的最大值。随着j的增加,Qj的横纵坐标都增加,P点也是一样的,因此这个斜率最大值可以用凸包维护三分查找,可以自己在纸上画个图看看
下面是自带大常数的代码
这道题需要注意细节…最好想清楚再写#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; int N , topp ; long long d , A[100005] , X[100005] , sum[100005] ; struct Vector{ double x , y ; Vector(){} ; Vector( double x_ , double y_ ): x(x_) , y(y_){} ; } ; typedef Vector Point ; typedef Vector Vv ; Vv operator - ( const Vv &A , const Vv &B ){ return Vector( A.x - B.x , A.y - B.y ) ;} double Cross( const Vv &A , const Vv &B ){ return A.x * B.y - A.y * B.x ; } Point p[100005] , a[100005] ; double K( int Q , int P ){ return 1.0 * ( sum[P] - p[Q].y ) / ( X[P] + a[P].x - p[Q].x ) ; } double calcu( int now ){ int lf = 1 , rg = topp ; double rt = 0 ; while( rg - lf >= 3 ){ int Lmid = lf + ( rg - lf ) / 3 , Rmid = rg - ( rg - lf ) / 3 ; if( K( Lmid , now ) < K( Rmid , now ) ) lf = Lmid ; else rg = Rmid ; } for( int i = lf ; i <= rg ; i ++ ) rt = max( rt , K( i , now ) ) ; return rt ; } void solve(){ double ans = 0 ; topp = 0 ; for( int i = 1 ; i <= N ; i ++ ){ while( topp >= 2 && Cross( a[i] - p[topp-1] , p[topp] - p[topp-1] ) >= 0 ) topp -- ; p[++topp] = a[i] ; ans += calcu( i ) ; } printf( "%.0f" , ans ) ; } int main(){ scanf( "%d%lld" , &N , &d ) ; for( int i = 1 ; i <= N ; i ++ ){ scanf( "%lld%lld" , &A[i] , &X[i] ) ; sum[i] = sum[i-1] + A[i] ; a[i] = Point( 1.0 * d * i , 1.0 * sum[i-1] ) ; } solve() ; }
相关文章推荐
- BZOJ 3203 Sdoi2013 保护出题人 凸包+三分
- [BZOJ3203][Sdoi2013]保护出题人(凸包+三分)
- [凸包 三分 数形结合] BZOJ 3203 [Sdoi2013]保护出题人
- BZOJ 3203 Sdoi2013 保护出题人 凸包+三分
- 3203: [Sdoi2013]保护出题人 凸包+三分
- 【bzoj3203】[Sdoi2013]保护出题人 凸包+二分
- 【BZOJ】【P3203】【Sdoi2013】【保护出题人】【题解】【凸包+三分】
- [BZOJ]3203 [SDOI2013] 保护出题人 三分
- 3203: [Sdoi2013]保护出题人|三分|凸包
- 【BZOJ】3203: [Sdoi2013]保护出题人(几何+三分+特殊的技巧)
- 【BZOJ3203】[Sdoi2013]保护出题人 二分+凸包
- bzoj 3203: [Sdoi2013]保护出题人 凸包
- bzoj3203 [Sdoi2013]保护出题人 凸包+二分
- bzoj3203【SDOI2013】保护出题人
- 【bzoj3203】【保护出题人】【凸包+三分】
- [bzoj3203][SDOI2013]保护出题人
- 【SDOI2013】【BZOJ3203】保护出题人
- 【bzoj3203】[Sdoi2013]保护出题人 凸包+三分法
- BZOJ3203 [Sdoi2013]保护出题人
- [bzoj3203][Sdoi2013]保护出题人