【JLOI2015】城池攻占(启发式合并)

传送门

开始想的是用树剖来维护

但发现因为对每个人都不一样而且又要一直修改,不是很好维护

其实也是可以维护的

按照点的dfsdfs序从上往下枚举

然后每个点都用树剖向其到根的路径上打上自己属性的标记

这样相当于每个人就都有走到根的比较了,直接二分找到第一个跑不了的位置

复杂度O(nlogm2+mlogm2)O(nlogm^2+mlogm^2)

但显然很不好写,码量窒息,树剖+线段树区间加区间乘区间最大值

还是启发式合并好写点

在洛谷上看到了一篇优先队列启发式合并

思路很不错

确实比左偏树要简单许多(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); 
}
posted @ 2018-12-31 20:35  Stargazer_cykoi  阅读(134)  评论(0编辑  收藏  举报