【JLOI2015】城池攻占(启发式合并)
开始想的是用树剖来维护
但发现因为对每个人都不一样而且又要一直修改,不是很好维护
其实也是可以维护的
按照点的序从上往下枚举
然后每个点都用树剖向其到根的路径上打上自己属性的标记
这样相当于每个人就都有走到根的比较了,直接二分找到第一个跑不了的位置
复杂度
但显然很不好写,码量窒息,树剖+线段树区间加区间乘区间最大值
还是启发式合并好写点
在洛谷上看到了一篇优先队列启发式合并的
思路很不错
确实比左偏树要简单许多(C++STL万岁!)
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define double long double
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
inline ll readl(){
char ch=getchar();
ll res=0;int f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=600005;
int adj[N],rt[N],n,m,nxt[N],to[N],fa[N],dep[N],ans[N],cnt,a[N],st[N],des[N];
ll h[N],v[N],add[N],mul[N];
struct knt{
double val;int id;
};
priority_queue<knt>q[N];
inline bool operator < (const knt&a,const knt&b){
return a.val>b.val;
}
inline ll get(double x){
return x-(ll)x<0.5 ? (ll)x:(ll)x+1;
}
inline void addedge(int u,int v){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
inline void merge(int u,int v){
if(q[rt[u]].size()<q[rt[v]].size())swap(rt[u],rt[v]);
while(q[rt[v]].size()){
ll ret=(q[rt[v]].top().val*mul[rt[v]]+add[rt[v]]),idx=q[rt[v]].top().id;q[rt[v]].pop();
q[rt[u]].push((knt){(double)(ret-add[rt[u]])/mul[rt[u]],idx});
}
}
inline void dfs(int u){
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
dfs(v),merge(u,v);
}
while(q[rt[u]].size()){
ll ret=(q[rt[u]].top().val*mul[rt[u]]+add[rt[u]]),idx=q[rt[u]].top().id;
if(ret<h[u])q[rt[u]].pop(),des[idx]=u;
else break;
}
if(!a[u])add[rt[u]]+=v[u];
else mul[rt[u]]*=v[u],add[rt[u]]*=v[u];
}
int main(){
int size=40<<20;//40M
//__asm__ ("movl %0, %%esp\n"::"r"((char*)malloc(size)+size));//调试用这个
__asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));//提交用这个
n=read(),m=read();dep[1]=1;
for(int i=1;i<=n;i++){
h[i]=readl(),rt[i]=i,mul[i]=1;
}
for(int i=2;i<=n;i++){
fa[i]=read(),dep[i]=dep[fa[i]]+1,addedge(fa[i],i),a[i]=read(),v[i]=readl();
}
for(int i=1;i<=m;i++){
ll v=readl();st[i]=read(),q[st[i]].push((knt){v,i});
}
dfs(1);
for(int i=1;i<=n;i++){
ans[des[i]]++;
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<'\n';
}
for(int i=1;i<=m;i++){
cout<<(dep[st[i]]-dep[des[i]])<<'\n';
}
exit(0);
}