bzoj4003
http://www.lydsy.com/JudgeOnline/problem.php?id=4003
可合并堆。
每个点都有一个小根堆,记住可以到这个点的骑士有哪些,以战斗力为关键字。
从底层到顶层不断合并,然后不断取出战斗力的最小值,如果小于防御值,则去掉最小值。
操作可以打标记。
我用了左偏树。
左偏树太不熟悉了,打错了2个地方,去了皮的大土豆~OTATO
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=; int N,M;
vector<int> son[maxN+];
vector<int> Q[maxN+];
int f[maxN+],dep[maxN+],a[maxN+];
LL h[maxN+],v[maxN+];
int c[maxN+];
LL s[maxN+]; struct Tnode
{
Tnode *l,*r;
LL v,mu,add;int id,dis;
inline Tnode(LL _v=,LL _mu=,LL _add=,int _id=,int _dis=){l=;r=;v=_v;mu=_mu;add=_add;id=_id;dis=_dis;}
inline int ldis(){return l?l->dis:;}
inline int rdis(){return r?r->dis:;}
inline void down()
{
if(mu== && add==)return;
if(l)l->v=l->v*mu+add,l->add=mu*l->add+add,l->mu=mu*l->mu;
if(r)r->v=r->v*mu+add,r->add=mu*r->add+add,r->mu=mu*r->mu;
mu=;add=;
}
}; inline Tnode *uni(Tnode *a,Tnode *b)
{
if(!a)return b;
if(!b)return a;
a->down();
b->down();
if(a->v > b->v)swap(a,b);
a->r=uni(a->r,b);
if(a->ldis() < a->rdis())swap(a->l,a->r);
a->dis=a->rdis()+;
return a;
} Tnode mem[maxN+];
Tnode *rt[maxN+]; int ge[maxN+],out[maxN+]; int main()
{
/*freopen("bzoj4003.in","r",stdin);
freopen("bzoj4003.out","w",stdout);*/
int i,j;
N=gint();M=gint();
re(i,,N)h[i]=gll();
re(i,,N)f[i]=gll(),a[i]=gint(),v[i]=gll(),son[f[i]].p_b(i);
re(i,,M)s[i]=gll(),c[i]=gint(),Q[c[i]].p_b(i);
re(i,,N)dep[i]=dep[f[i]]+;
re(i,,M)mem[i]=Tnode(s[i],,,i,);
red(i,N,)
{
re(j,,int(son[i].size())-)
{
int ch=son[i][j];
rt[i]=uni(rt[i],rt[ch]);
}
re(j,,int(Q[i].size())-)
{
int t=Q[i][j];
rt[i]=uni(rt[i],&mem[t]);
}
while(rt[i] && rt[i]->v<h[i])
{
ge[i]++;
int t=rt[i]->id;
out[t]=dep[c[t]]-dep[i];
rt[i]->down();////////////////////////////////////////////注意这里要down
rt[i]=uni(rt[i]->l,rt[i]->r);
}
if(rt[i])
if(a[i]==)
rt[i]->v+=v[i],rt[i]->add+=v[i];
else
rt[i]->v*=v[i],rt[i]->mu*=v[i],rt[i]->add*=v[i];
}
while(rt[])
{
int t=rt[]->id;
out[t]=dep[c[t]];
rt[]->down();////////////////////////////////////////////注意这里要down
rt[]=uni(rt[]->l,rt[]->r);
}
re(i,,N)PF("%d\n",ge[i]);
re(i,,M)PF("%d\n",out[i]);
return ;
}
然后有另外一种不适用这题的方法。
我们发现,如果某个骑士的初始战斗力为x,那么骑士在当前点的战斗力为ax+b,其实a和b只跟出发点和当前点的位置有关,与x无关。
并且我们发现a一定是正数。
类似于LCA,
to[i][j]表示i号点跳2^j次到的点。
jump[i][j]表示,这是一个pair,表示一个初始位置在i号点的骑士的初始战斗力为x,跳2^j次后,战斗力变成jump[i][j].fi*x+jump[i][j].se,其实jump[i][j].fi和jump[i][j].se只和i,有关,与x无关。
minx[i][j]表示,一个初始位置在i号点的骑士的初始战斗力为x,想要跳2^j次,x至少要为minx[i][j]。
容易发现x[i][j]随着j的递增而递增,有单调性。
可以用nlogn的时间求出。
然后对于初始位置在i的骑士,记其初始战斗力为x,二分j,判断x与minx[i][j]的大小关系即可。
但是这道题不适用的地方在于:
(1)MLE
(2)题目保证“任何时候骑士战斗力值的绝对值不超过 10^18”,不是"骑士跑到到根战斗力值的绝对值不超过 10^18“,这样很容易就爆longlong了。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<LL,LL> PLL;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const LL INF=(1LL<<)-; int N,M;
LL s[maxN+];int c[maxN+];
int f[maxN+],a[maxN+];
LL h[maxN+],v[maxN+]; int dep[maxN+];
int to[maxN+][];
PLL jump[maxN+][];
LL minx[maxN+][]; int g[maxN+],out[maxN+]; int main()
{
freopen("bzoj4003.in","r",stdin);
freopen("bzoj4003.out","w",stdout);
int i,j;
N=gint();M=gint();
re(i,,N)h[i]=gll();
re(i,,N)f[i]=gint(),a[i]=gint(),v[i]=gll();
re(i,,M)s[i]=gll(),c[i]=gint(); dep[]=;
re(j,,)to[][j]=;
re(j,,)jump[][j]=PLL(,);
re(j,,)minx[][j]=INF;
re(i,,N)
{
dep[i]=dep[f[i]]+;
to[i][]=f[i];
re(j,,)to[i][j]=to[to[i][j-]][j-];
if(a[i]==) jump[i][]=PLL(,v[i]); else jump[i][]=PLL(v[i],);
re(j,,)
{
LL da=jump[i][j-].fi,db=jump[i][j-].se,a=jump[to[i][j-]][j-].fi,b=jump[to[i][j-]][j-].se;
jump[i][j]=PLL(a*da,a*db+b);
}
minx[i][]=h[i];
re(j,,)
{
minx[i][j]=minx[i][j-];
LL a=jump[i][j-].fi,b=jump[i][j-].se,temp=minx[to[i][j-]][j-];
if(temp==INF) upmax(minx[i][j],INF); else upmax(minx[i][j],(temp-b-)/a+);
}
} re(i,,M)
{
int p=c[i];LL x=s[i];
red(j,,)
if(x>=minx[p][j])
{
x=x*jump[p][j].fi+jump[p][j].se;
p=to[p][j];
}
if(x<h[p])g[p]++;
out[i]=dep[c[i]]-dep[p];if(x>=h[p])out[i]++;
} re(i,,N)PF("%d\n",g[i]);
re(i,,M)PF("%d\n",out[i]); return ;
}
bzoj4003的更多相关文章
- 左偏树初步 bzoj2809 & bzoj4003
看着百度文库学习了一个. 总的来说,左偏树这个可并堆满足 堆的性质 和 左偏 性质. bzoj2809: [Apio2012]dispatching 把每个忍者先放到节点上,然后从下往上合并,假设到了 ...
- BZOJ4003 [JLOI2015]城池攻占 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4003 题意概括 题意有点复杂,直接放原题了. 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑 ...
- 【BZOJ4003】[JLOI2015]城池攻占 可并堆
[BZOJ4003][JLOI2015]城池攻占 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池. 这 n 个城池用 1 到 n 的整数表示.除 1 号 ...
- [BZOJ4003][JLOI2015]城池攻占(左偏树)
这题有多种做法,一种是倍增预处理出每个点往上走2^i步最少需要的初始战斗力,一种是裸的启发式合并带标记splay. 每个点合并能攻占其儿子的所有骑士,删去所有无法攻占这个城市的骑士并记录答案. 注意到 ...
- [bzoj4003][JLOI2015]城池攻占_左偏树
城池攻占 bzoj-4003 JLOI-2015 题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上.每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城 ...
- BZOJ4003 [JLOI2015]城池攻占
这题有两种做法来着... 第一种就是一开始想到的比较不靠谱,不过貌似可以过掉: 看从$1$号节点开始到$p$号节点最大需要的体力,记录单调上升的体力,询问的时候二分跳着走就可以了 不过精度问题还有可能 ...
- 【BZOJ4003】【JLOI2015】城池攻占(左偏树)
题面 题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi ...
- 【BZOJ4003】【JLOI2015】城池攻占
Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其 ...
- 左偏树(BZOJ4003)
左偏树打个标记,没了. #include <cstdio> #include <vector> using namespace std; typedef long long l ...
随机推荐
- spring整合springMVC、mybatis、hibernate、mongodb框架
开发环境 eclipse Mars 4.5 JDK 1.7 框架 spring 4.0.5 mybatis 3.2.7 hibernate 4.3.6 mongodb 1.7 数据库 MySQL 5. ...
- (转)iOS 各种控件默认高度(图示)
1.状态栏 状态栏一般高度为20像素,在打手机或者显示消息时会放大到40像素高,注意,两倍高度的状态栏在好像只能在纵向的模式下使用.如下图 用户可以隐藏状态栏,也可以将状态栏设置为灰色,黑色或者半透明 ...
- apache archiva安装教程
1. 下载archiva standalone http://archiva.apache.org/download.cgi 2. 解压,设置ARCHIVA_HOME 环境变量 3.为了防止冲突, ...
- HtmlParser 2.0 中文乱码问题
对于HTMLParser 2.0 工具包我们需要修改其中的Page.java文件使其适用中文的html文件分析. 主要是把protected static final String DEFAULT_C ...
- CSS3新特性(阴影、动画、渐变、变形、伪元素等) CSS3与页面布局学习总结——CSS3新特性(阴影、动画、渐变、变形、伪元素等)
目录 一.阴影 1.1.文字阴影 1.2.盒子阴影 二.背景 2.1.背景图像尺寸 2.2.背景图像显示的原点 三.伪元素 3.1.before 3.2.after 3.3.清除浮动 四.圆角与边 ...
- Dev系列控件的AJAX (转)
介绍Dev系列控件在前台也就是客户端的一些常用方法介绍以及前后台异步通信的方法. 一.Dev Data Edit控件通用属性以及方法: 属性 1.GetEnabled():返回控件是否为可操作状态 2 ...
- Windows 右键快速运行命令行
原文见:右键命令行 - yacper - 博客园 方法一:配置文件夹选项 1 打开人任意文件夹,[工具] --> [文件夹选项] --> [文件类型] --> [(无)资料夹] -- ...
- C# winform DataTable 批量数据处理 增、删、改 .
1.批量新增,采用高效的SqlBulkCopy SqlBulkCopy DTS = new System.Data.SqlClient.SqlBulkCopy(con); DTS.NotifyAfte ...
- [FileStream] 使用
// 要上传的文件 FileStream fs = new FileStream(路径, FileMode.Open, FileAccess.Read); FileMode 是指确定如何打开或创建文件 ...
- hdu2937
题目大意: 给出n求sn,中括号代表向下取整. 为了方便表述,我们令a = (3k+6)!,b = (3k+7),令c = (a+1)/b也就是式子中的前半部分,d = a/b也就是式子中的后半部分. ...