好像所有人都写的左偏树 但我不会啊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 城池攻占 (倍增)的更多相关文章

  1. 【BZOJ】【4003】【JLOI2015】城池攻占

    可并堆 QAQ改了一下午……最终弃疗求助zyf……居然被秒了QAQ真是弱到不行(zyf太神了Orz) 还是先考虑部分分的做法: 1.$n,m\leq 3000$:可以暴力模拟每个骑士的攻打过程,也可以 ...

  2. BZOJ_4003_[JLOI2015]城池攻占_可并堆

    BZOJ_4003_[JLOI2015]城池攻占_可并堆 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 ...

  3. 「JLOI2015」城池攻占 解题报告

    「JLOI2015」城池攻占 注意到任意两个人的战斗力相对大小的不变的 可以离线的把所有人赛到初始点的堆里 然后做启发式合并就可以了 Code: #include <cstdio> #in ...

  4. 【BZOJ4003】[JLOI2015]城池攻占 可并堆

    [BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...

  5. [bzoj4003][JLOI2015]城池攻占_左偏树

    城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...

  6. [洛谷P3261] [JLOI2015]城池攻占(左偏树)

    不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...

  7. BSOJ 4591 -- 【JLOI2015】城池攻占

    Description 小铭铭最近获得了一副新的桌游,游戏中需要用m个骑士攻占n个城池. 这n个城池用1到n的整数表示.除1号城池外,城池i会受到另一座城池fi的管辖,其中fi 每个城池有一个防御值h ...

  8. BZOJ 4003 【JLOI2015】城池攻占

    Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖, ...

  9. 【BZOJ4003】【JLOI2015】城池攻占(左偏树)

    题面 题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi ...

随机推荐

  1. HTTPS的SSL证书配置

    SSL证书 TOMCAT7.0部署_百度经验https://jingyan.baidu.com/article/7082dc1c65066be40a89bda8.html SSL证书安装指引 - 青春 ...

  2. Windows 10正式版历代记:Version 和 Build 对应关系

    2017年10月中下旬,微软面向正式版用户推送了Windows 10创意者更新秋季版.这是自发布以来,Windows 10的第五个大版本. 在这篇文章中,我们来回顾一下Windows 10正式版的历史 ...

  3. 3 The simple past

    1 许多动词通过在原型之后添加-ed 构成一般过去式. 其他动词有不规则的过去式,使用一般过去式的时间词语出现在句首或者句尾 The company grew from 400 to 5,000 pe ...

  4. [转帖]Runtime, Engine, VM 的区别是什么?

    这就是个WiFi和WLAN关系的问题嘛.Runtime是指用于支持程序运行时的组件,它可以是个Engine和/或VM.VM是一种系统抽象,它提供代码执行所需的API环境.Engine是一种处理抽象,它 ...

  5. Python 基础知识----数据类型

    一.Number 类型(数值类型) 二.String 类型 (字符串类型) 三.List 类型 (列表类型) 是一种常用的序列类型簇,List 用中括号 [ ] 表示,不同的元素(任意类型的值)之间以 ...

  6. 关于事务回滚,rollback tran到底要不要写?

    关于事务回滚,有些不明白,不知道rollback tran在什么时候用. begin tran update 表1 update 表2 commit tran 这种写法,在更新表1或表2时出错,事务会 ...

  7. Lodop扁宽横向241mm*93mm这种怪异的纸张如何设置

    Lodop中如果设置LODOP.SET_PRINT_PAGESIZE(2,'241mm','93mm','');,会发现实际的纸张和自己设置的不同,不只是打印机不识别,xps和pdf虚拟打印机也不能正 ...

  8. OPENQUERY (Transact-SQL)

    Syntax Copy OPENQUERY ( linked_server ,'query' ) Arguments linked_serverIs an identifier representin ...

  9. cf- Educational Codeforces Round 40 -D

    题意:给你n个点,m条边,一个起点s,一个终点t的无向图,问在某两个点之间加一条边,不改变s到t的最短路径的值的加法有多少种,所有点一定连接: 思路:首先,默认相邻两点的权值都为1,会改变值的情况有: ...

  10. JarvisOJ Basic 美丽的实验室Logo

    出题人丢下个logo就走了,大家自己看着办吧 扔进01Editor中,发现最后有14844个不属于jpg的字节 扔进Kali中用dd命令提取出附加的文件,可以看到也是一个图片,图片上的文字即是flag