THUSC2013
魔塔
BZOJ
设每个敌人的属性值为\(hp_i,atk_i,def_i\)。自己的为\(HP,ATK,DEF\)
首先我们可以发现顺序是没有影响的。
然后我们可以发现合适的\(ATK\)一定满足\(\max(hp_i+def_i)\ge ATK>\max(def)\),\(DEF\)一定满足\(DEF\le\max(atk_i)\)。
对于一个确定的\(ATK,DEF\),我们可以计算出\(HP=\sum(\lceil\frac{hp_i}{ATK-def_i}\rceil\max(0,atk_i-DEF))+1\)。
也就是说总费用是一个关于\(ATK,DEF\)的二元函数。
看到\(\lceil\frac{hp_i}{ATK-def_i}\rceil\)我们会马上想到除法分块,这东西最多有\(\sqrt{hp_i}\)个取值。因为所有的属性值都是\(1e6\)级别的,所以总的取值个数是\(n\sqrt{1e6}\)级别的。当然我们的\(ATK\)最大只能取到\(2e6\)。
所以我们考虑,假如我们固定了一个\(ATK\),设\(f(x)\)表示此时\(DEF\ from\ x-1\ to\ x\)的\(-\Delta HP\)。\(f(x)\)显然是一个分段函数。
如果你对“\(ATK-DEF\)”这类的计算公式有一定了解的话,可以直接得出下面两个结论:
\(1.f(x)\)严格单调不增。
\(2.\)随着\(ATK\)的增加,\(f(x)\)严格单调不增。
一句话理解就是\(ATK,DEF\)都具有边界效应。
详细点讲的话,
\(1.\)当\(DEF\)增大时,\(\max(0,atk_i-DEF)\)会有越来越多的取到\(0\),也就是\(HP\)递减的速度越来越慢,即\(f(x)\)严格单调不增。
\(2.\)随着\(ATK\)递增,\(\lceil\frac{hp_i}{ATK-def_i}\rceil\)递减,也就是\(HP\)递减的速度越来越慢,即\(f(x)\)严格单调不增。
根据第一条性质,我们可以在固定一个\(ATK\)时,通过二分找到第一个\(f(x)<Cost_{DEF}\)的位置,从而找到最优的\(DEF\)。
根据第二条性质,当\(ATK\)增大时,第一个\(f(x)<Cost_{DEF}\)的位置一定只会向左移,我们可以维护一个单调指针来找到最优的\(DEF\)。
然后讲下如何具体维护\(f(x)\)。
当\(ATK\ from\ x-1\ to\ x\),会有部分\(\lceil\frac{hp_i}{ATK-def_i}\rceil\)发生\(-1\)的变化从而导致\(f(x)\)变化。
观察可以发现这个变化相当于对\(f(x)\)的一段前缀减一个数。并且根据上文除法分块部分的分析总的变化次数大概是\(1e7\)级别的。
因为最优\(DEF\)是单调左移的,所以我们可以直接把前缀减反映到差分数组上(即减的最后一位),在\(DEF\)指针左移时直接计算影响,如果这个前缀超过了\(DEF\),那么超过\(DEF\)的部分是没有影响的。
然后这题卡空间,需要用链表/前向星。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int read(){int x;scanf("%d",&x);return x;}
const int N=2000007;
int n,ca,cd,mx,ATK,DEF,head[N],ver[N*5],Next[N*5],edge[N*5],tot;ll a[N],ans,sum,HP,X,Y,Z;
void add(int x,int y,int id){ver[++tot]=x,Next[tot]=head[id],edge[tot]=y,head[id]=tot;}
void update(int p,int v){a[p]+=v;if(Y<=p)sum+=v,Z+=(p-Y)*v;}
int main()
{
n=read(),ca=read(),cd=read(),ans=1e18,Y=1e6,Z=1;
for(int i=1,l,hp,atk,def;i<=n;++i)
{
hp=read()-1,atk=read(),def=read();
for(l=1;l<=hp;l=(hp/(hp/l))+1) if(l==1) add(atk,hp+1,def+1); else add(atk,hp/l-hp/(l-1),def+l);
add(atk,-1,hp+def+1),mx=max(mx,def);
}
for(X=1;X<=2e6;++X)
{
for(int i=head[X];i;i=Next[i]) update(ver[i],edge[i]);
if(X<=mx) continue;
while(Y>1&&sum<cd) Z+=sum,sum+=a[--Y];
if(Z+X*ca+Y*cd<=ans) ans=Z+X*ca+Y*cd,ATK=X,DEF=Y,HP=Z;
}
printf("%lld %d %d",HP,ATK,DEF);
}
宇宙飞艇
BZOJ
第一问随便做,把所有在这个方向的分速度为正的向量全部加上就行了。
第二问可以根据这个扩展一个写法。
随便钦定一个单位向量,把题目给的向量按在这个方向上的分量降序排序。
考虑我们旋转这个单位向量,这个次序会随之变化对吧,也就是有\(n\choose2\)个分界点,经过这个分界点时有两个向量的次序会交换。
假如有多个连续的向量同时交换,那么我们应该reverse而不是一个个swap。(可以自己画图模拟)
可以发现最优的答案一定会在分界点取到。
那么我们顺时针枚举一遍,维护次序数组,每次取在这个方向上分量为正的就行了,最后去最大值。
假如强制选\(k\)个,那就取当前次序前\(k\)个就行了。
#include<bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
int read(){int x;scanf("%d",&x);return x;}
ll max(ll a,ll b){return a>b? a:b;}
const int N=1007;
int n,m,id[N],pos[N],bd[N];vector<int>in;
struct vec{ll x,y;ld arg;vec(int a=0,int b=0):x(a),y(b),arg(atan2(b,a)){}}a[N],ans[N],sum[N],q;
ll len(vec&a){return a.x*a.x+a.y*a.y;}
vec operator+(vec&a,vec&b){return vec(a.x+b.x,a.y+b.y);}
ll operator*(vec&a,vec&b){return a.x*b.x+a.y*b.y;}
int operator==(vec&a,vec&b){return a.x*b.y==a.y*b.x;}
struct line{int a,b;vec x;}b[N*N];
void max(vec&a,vec&b){if(len(b)>len(a))a=b;}
int main()
{
n=read(),q.x=read(),q.y=read();ll tmp=0;
for(int i=1;i<=n;++i) a[i].x=read(),a[i].y=read(),tmp+=max(0ll,a[i]*q),id[i]=i;
printf("%lld\n",tmp);
for(int i=1,j;i<=n;++i) for(j=i+1;j<=n;++j) b[++m]={i,j,vec(a[i].y-a[j].y,a[j].x-a[i].x)},b[++m]={i,j,vec(a[j].y-a[i].y,a[i].x-a[j].x)};
sort(b+1,b+m+1,[&](const line&a,const line&b){return a.x.arg<b.x.arg;});
sort(id+1,id+n+1,[](int i,int j){return a[i].x<a[j].x||(a[i].x==a[j].x&&a[i].y<a[j].y);});
for(int i=1;i<=n;++i) ans[i]=sum[i]=sum[i-1]+a[id[pos[id[i]]=i]];
for(int l=1,r,x,y,i;l<=m;l=r)
{
r=l,in.clear();
for(;r<=m&&b[r].x==b[l].x;++r)
{
x=pos[b[r].a],y=pos[b[r].b];
if(x>y) swap(x,y);
if(!bd[x]) in.push_back(x);
bd[x]=max(bd[x],y);
}
sort(in.begin(),in.end());
for(int x:in)
{
if(!bd[x]) continue;
reverse(id+x,id+(y=bd[x])+1);
for(i=x;i<=y;++i) pos[id[i]]=i,bd[i]=0,max(ans[i],sum[i]=sum[i-1]+a[id[i]]);
}
}
tmp=0;
for(int i=1;i<=n;++i) tmp=max(tmp,len(ans[i]));
printf("%lld\n",tmp);
for(int i=1;i<=n;++i) printf("%lld ",len(ans[i]));
}
THUSC2013的更多相关文章
- BZOJ4141 THUSC2013 魔塔 贪心
没得传送门 考虑当\(Atk\)增大时,\(Def\)一定越来越没用,因为回合数在变少.所以考虑从小到大枚举\(Atk\)然后双指针计算. 设\(f_i(x)\)表示在\(Atk = i\)时,\(D ...
随机推荐
- springboot之搭建第一个helloworld程序
1.下载基本框架 在网站:https://start.spring.io/ 全部默认,基本没有改动 选择依赖,当然也可以自己在pom.xml加,我们直接在这里选择. 只选择Spring Web Sta ...
- Ubuntu14.04(indigo)实现RGBDSLAMv2(数据集和实时Kinect)
Ubuntu14.04(indigo)实现RGBDSLAMv2(数据集和实时Kinect v2) 一.在.bag数据集上跑RGBDSLAMv2 RGBDSLAMv2指的是Felix Endres大神在 ...
- Apache Flink - 分布式运行环境
1.任务和操作链 下面的数据流图有5个子任务执行,因此有五个并行线程. 2.Job Managers, Task Managers, Clients Job Managers:协调分布式运行,他们安排 ...
- CentOS7.4搭建ftp服务
1.使用yum安装vsftpd yum install vsftpd -y 2.安装完成后,启动 FTP 服务: service vsftpd start 3.配置ftp权限 目前 FTP 服务登陆允 ...
- python+Django+mysql环境搭建
为什么我的毕业设计还要用到网站啊啊啊啊.什么鬼啊,又要做爱拍拍又要做网站???饶了我啊..我选择狗带.. 网站就用django做吧,毕竟之前做过一个电脑销售网站,希望能借鉴一下经验什么的,不要一切从头 ...
- C语言和Python语言在存储变量方面的不同
C语言和Python语言在存储变量方面的不同 众所周知,Python是脚本语言,边解释边执行,而C语言是编译型语言 存储变量: C语言定义变量,变量本身代表的就是大小,任何一个字母或者数字 符号均可以 ...
- WEB-INF目录下登录表单提交的重定向
问题描述 登陆表单提交跳转后刷新会重新提交表单,但是使用重定向时不走视图解析器,不能访问WEB-INF下的资源 解决方法 原方法 @RequestMapping(value = "/logi ...
- linux系统安装Memcache
Linux系统安装memcached 首先要先安装libevent库. centos 下执行 yum install libevent libevent-devel 查看memcached 是否已经 ...
- 【MYSQL】存储过程示例
GROUPEMP_EXISTS: ), ), )) LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT ' ...
- 001-多线程-锁-架构【同步锁、JUC锁】
一.概述 Java中的锁,可以分为"同步锁"和"JUC包中的锁". 1.1.同步锁 即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁 ...