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的更多相关文章

  1. 左偏树初步 bzoj2809 & bzoj4003

    看着百度文库学习了一个. 总的来说,左偏树这个可并堆满足 堆的性质 和 左偏 性质. bzoj2809: [Apio2012]dispatching 把每个忍者先放到节点上,然后从下往上合并,假设到了 ...

  2. BZOJ4003 [JLOI2015]城池攻占 左偏树 可并堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4003 题意概括 题意有点复杂,直接放原题了. 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑 ...

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

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

  4. [BZOJ4003][JLOI2015]城池攻占(左偏树)

    这题有多种做法,一种是倍增预处理出每个点往上走2^i步最少需要的初始战斗力,一种是裸的启发式合并带标记splay. 每个点合并能攻占其儿子的所有骑士,删去所有无法攻占这个城市的骑士并记录答案. 注意到 ...

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

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

  6. BZOJ4003 [JLOI2015]城池攻占

    这题有两种做法来着... 第一种就是一开始想到的比较不靠谱,不过貌似可以过掉: 看从$1$号节点开始到$p$号节点最大需要的体力,记录单调上升的体力,询问的时候二分跳着走就可以了 不过精度问题还有可能 ...

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

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

  8. 【BZOJ4003】【JLOI2015】城池攻占

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

  9. 左偏树(BZOJ4003)

    左偏树打个标记,没了. #include <cstdio> #include <vector> using namespace std; typedef long long l ...

随机推荐

  1. 【Ruby on Rails学习二】在线学习资料的整理

    由于工作任务重,时间紧,没有太多学习的时间,大致找了些在线学习资料,这里做个整理,希望对同样准备学习的朋友有帮助 在线文档类: Ruby on Rails 实战圣经  使用 Rails 4.2 及 R ...

  2. SpringMVC文件上传与下载

    一.关键步骤 ①引入核心JAR文件 SpringMVC实现文件上传,需要再添加两个jar包.一个是文件上传的jar包,一个是其所依赖的IO包.这两个jar包,均在Spring支持库的org.apach ...

  3. (原)Mac下Apache添加限制IP线程模块:mod_limitipconn.so

    1.下载:http://dominia.org/djao/limit/mod_limitipconn-0.24.tar.bz2 解压到一个目录:我的是~/Download/mod_limitipcon ...

  4. (转)在Android的webview中定制js的alert,confirm和prompt对话框的方法

    1.首先继承android.webkit.WebChromeClient实现MyWebChromeClient. 2.在MyWebChromeClient.java中覆盖onJsAlert,onJsC ...

  5. [转载]ios app 发布遇到的问题uinewsstandapp=true

    原文地址:ios app 发布遇到的问题uinewsstandapp=true 作者:Capacity To include newsstand features, the info.plist mu ...

  6. hadoop权威指南 chapter2 MapReduce

    MapReduce MapReduce is a programming model for data processing. The model is simple, yet not too sim ...

  7. Android(java)学习笔记261:JNI之编写jni程序适配所有处理器型号

    1. 还是以"02_两个数相加"为例,你会发现这个jni程序只能在ARM处理器下运行,如下:  如果我们让上面的程序运行在x86模拟器上,处理平台不对应,报如下错误: 03-29 ...

  8. include子页面传递过来的参数传递到后台

    在页面上可以使用 ${param.moduleId}来获取 在判断中也可以使用${param.moduleId == "test" ? "1":"2& ...

  9. Android-兼容问题

    兼容性问题从何而来?答:使用了低版本没有的功能,可是目标设备包括低版本. 那我们如何解决兼容性问题? 1.如果是JAVA代码 1.1 使用TargetApi(x)注解,避免Android Lint报错 ...

  10. 初学Java ssh之Spring 第二篇

    上一篇我们成功搭建好了spring开发的环境,接下来一起看看spring有什么神奇的地方吧(本人也是新手,有不太对的地方希望大神给指出便于修改呢,谢谢大家). 之前听说spring是在对xml文件的应 ...