luogu3621 城池攻占 (倍增)
好像所有人都写的左偏树 但我不会啊233
首先发现乘的时候 系数不会为负,所以能得到一个关键条件:变化后的战斗力随变化前的战斗力大小单调
所以我们考虑倍增
设hp[x][i]是从x开始一路攻克$2^i$个城池所需要最小的初始生命值
设trans[x][i][0/1]是攻克了$2^i$个城池后攻击力的变化量,0表示乘,1表示加,先乘后加
然后就可以倍增了
#include<bits/stdc++.h>
#define pa pair<ll,ll>
#define CLR(a,x) memset(a,x,sizeof(a))
#define MP make_pair
using namespace std;
typedef long long ll;
const int maxn=3e5+; inline char gc(){
return getchar();
static const int maxs=<<;static char buf[maxs],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,maxs,stdin),p1==p2)?EOF:*p1++;
}
inline ll rd(){
ll x=;char c=gc();bool neg=;
while(c<''||c>''){if(c=='-') neg=;c=gc();}
while(c>=''&&c<='') x=(x<<)+(x<<)+c-'',c=gc();
return neg?(~x+):x;
} int N,M,fa[maxn][];
ll hp[maxn][],trans[maxn][][];
int ans1[maxn],ans2[maxn]; int main(){
//freopen("","r",stdin);
int i,j,k;
N=rd(),M=rd();
for(i=;i<=N;i++) hp[i][]=rd();
fa[][]=N+;
for(i=;i<=N;i++){
fa[i][]=rd();
ll x=rd(),y=rd();
trans[i][][]=;
trans[i][][!x]=y;
for(j=;fa[i][j]&&fa[fa[i][j]][j];j++){
fa[i][j+]=fa[fa[i][j]][j];
hp[i][j+]=max(hp[i][j],(ll)ceil(1.0*(hp[fa[i][j]][j]-trans[i][j][])/trans[i][j][]));
trans[i][j+][]=trans[i][j][]*trans[fa[i][j]][j][]+trans[fa[i][j]][j][];
trans[i][j+][]=trans[i][j][]*trans[fa[i][j]][j][];
}
}
for(i=;i<=M;i++){
ll s=rd();int x=rd(),n=;
for(j=;j>=&&x!=-;j--){
if(fa[x][j]&&hp[x][j]<=s){
s=s*trans[x][j][]+trans[x][j][];
x=fa[x][j];
n+=<<j;
}
}
if(x!=-) ans1[x]++;
ans2[i]=n;
}
for(i=;i<=N;i++)
printf("%d\n",ans1[i]);
for(i=;i<=M;i++)
printf("%d\n",ans2[i]); return ;
}
好好分析空间啊kora!
然而空间大小恶意卡倍增
但是我们这个倍增可以换成三进制的2333
就是把定义里的$2^i$都换成$3^i$
于是$log_3300000=10$,空间就变成了原来的一半
需要注意的一点是,最后在跳倍增的时候,同一个长度可以跳两次(因为是三进制嘛),循环的时候稍微注意一下
#include<bits/stdc++.h>
#define pa pair<ll,ll>
#define CLR(a,x) memset(a,x,sizeof(a))
#define MP make_pair
using namespace std;
typedef long long ll;
const int maxn=3e5+; inline char gc(){
return getchar();
static const int maxs=<<;static char buf[maxs],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,maxs,stdin),p1==p2)?EOF:*p1++;
}
inline ll rd(){
ll x=;char c=gc();bool neg=;
while(c<''||c>''){if(c=='-') neg=;c=gc();}
while(c>=''&&c<='') x=(x<<)+(x<<)+c-'',c=gc();
return neg?(~x+):x;
} int N,M,fa[maxn][];
ll hp[maxn][],trans[maxn][][];
int ans1[maxn],ans2[maxn];
int pw3[]; int main(){
//freopen("","r",stdin);
int i,j,k;
pw3[]=;for(i=;i<=;i++) pw3[i]=pw3[i-]*;
N=rd(),M=rd();
for(i=;i<=N;i++) hp[i][]=rd();
fa[][]=N+;
for(i=;i<=N;i++){
fa[i][]=rd();
ll x=rd(),y=rd();
trans[i][][]=;
trans[i][][!x]=y;
for(j=;j<;j++){
int f=fa[i][j],ff=fa[f][j];
if(!f||!ff||!fa[ff][j]) break;
fa[i][j+]=fa[ff][j];
ll hp1=max(hp[f][j],(ll)ceil(1.0*(hp[ff][j]-trans[f][j][])/trans[f][j][]));
hp[i][j+]=max(hp[i][j],(ll)ceil(1.0*(hp1-trans[i][j][])/trans[i][j][]));
trans[i][j+][]=trans[i][j][]*trans[f][j][]+trans[f][j][];
trans[i][j+][]=trans[i][j][]*trans[f][j][];
trans[i][j+][]=trans[i][j+][]*trans[ff][j][]+trans[ff][j][];
trans[i][j+][]=trans[i][j+][]*trans[ff][j][];
}
}
for(i=;i<=M;i++){
ll s=rd();int x=rd(),n=;
for(j=;j>=&&x!=-;j--){
if(fa[x][j]&&hp[x][j]<=s){
s=s*trans[x][j][]+trans[x][j][];
x=fa[x][j];
n+=pw3[j];j++;
}
}
if(x!=-) ans1[x]++;
ans2[i]=n;
}
for(i=;i<=N;i++)
printf("%d\n",ans1[i]);
for(i=;i<=M;i++)
printf("%d\n",ans2[i]); return ;
}
luogu3621 城池攻占 (倍增)的更多相关文章
- 【BZOJ】【4003】【JLOI2015】城池攻占
可并堆 QAQ改了一下午……最终弃疗求助zyf……居然被秒了QAQ真是弱到不行(zyf太神了Orz) 还是先考虑部分分的做法: 1.$n,m\leq 3000$:可以暴力模拟每个骑士的攻打过程,也可以 ...
- BZOJ_4003_[JLOI2015]城池攻占_可并堆
BZOJ_4003_[JLOI2015]城池攻占_可并堆 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 ...
- 「JLOI2015」城池攻占 解题报告
「JLOI2015」城池攻占 注意到任意两个人的战斗力相对大小的不变的 可以离线的把所有人赛到初始点的堆里 然后做启发式合并就可以了 Code: #include <cstdio> #in ...
- 【BZOJ4003】[JLOI2015]城池攻占 可并堆
[BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...
- [bzoj4003][JLOI2015]城池攻占_左偏树
城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...
- [洛谷P3261] [JLOI2015]城池攻占(左偏树)
不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...
- BSOJ 4591 -- 【JLOI2015】城池攻占
Description 小铭铭最近获得了一副新的桌游,游戏中需要用m个骑士攻占n个城池. 这n个城池用1到n的整数表示.除1号城池外,城池i会受到另一座城池fi的管辖,其中fi 每个城池有一个防御值h ...
- BZOJ 4003 【JLOI2015】城池攻占
Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖, ...
- 【BZOJ4003】【JLOI2015】城池攻占(左偏树)
题面 题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi ...
随机推荐
- Java 数据库操作
目录 Java数据库组织架构 下载驱动包 连接数据库 连接数据库的三个步骤 连接数据库的高开销 Statement接口介绍 PreparedStatement类 使用PreparedStatement ...
- (自用 )npm --save和--save-dev区别
https://blog.csdn.net/playboyanta123/article/details/78349034(原文) 目前大多数基于vue的项目都是用vue-cli 创建的.当创建项目完 ...
- from组件补充
一.定义的规则 class TeacherForm(Form): #必须继承Form # 创建字段,本质上是正则表达式 username = fields.CharField( required=Tr ...
- Spring Boot 框架学习 (一)配置并运行Spring Boot 框架
下载开发工具: 下载完成打开以后,第一步检查环境 查看jdk是否配置: 接着一定要注意,maven通常情况下它是没有给你配置的,要自行配置: 右键新建: 然后依赖选择web.跟Mybatis就行了. ...
- Debian下配置防火墙iptables
debian下iptables输入命令后即时生效,但重启之后配置就会消失,可用iptables-save快速保存配置,因为Debian上iptables是不会保存规则的,然后在开机自动的时候让ipta ...
- myisam和innodb的区别对比
1.MyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法.不 ...
- qtp 自动货测试桌面程序-笔记(使用函数)
新建-function 写入函数 rem 关闭出现错误窗口Function checkExist() If Window("出现错误").WinObject("确定&qu ...
- 【数模】day06-数理统计I
数理统计. 以样本推断总体,进而用总体研究问题. 分两部分学习,第一部分是基础统计.参数估计.假设检验以及bootstrap方法. 1. 基础统计 假设有如下数据: 要做频数表.直方图.折线图.饼状图 ...
- Tomcat服务的安装与配置
介绍 百度百科 Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开 ...
- Navicat MySQL 自动备份
1 新建批处理作业 2 设定(多个库,就轮流选择不同库,然后步骤2) 最后记得保存 3 计划 4 设计批处理作业->设置计划任务 5 输入账号和密码 服务器登录名 服务器密码 6 你可以修改备份 ...