BZOJ4003:[JLOI2015]城池攻佔
阿新 • • 發佈:2019-01-10
淺談左偏樹:https://www.cnblogs.com/AKMer/p/10246635.html
題目傳送門:https://lydsy.com/JudgeOnline/problem.php?id=4003
從下往上合併左偏樹然後把戰鬥力低的踢掉。做完之後打標記。因為不會乘負數所以小根堆的性質不會被破壞。
不知道為什麼用\(struct\)封裝左偏樹會\(RE\),改成\(namespace\)之後才\(AC\)。
時間複雜度:\(O(nlogn)\)
空間複雜度:\(O(n)\)
程式碼如下:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn=3e5+5; bool a[maxn]; int dep[maxn]; ll h[maxn],v[maxn]; int n,m,tot,rt[maxn],ans[maxn]; int now[maxn],pre[maxn],to[maxn]; struct Knight {int c,ans;ll s;}p[maxn]; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } ll READ() { ll x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } void add(int a,int b) { pre[++tot]=now[a]; now[a]=tot,to[tot]=b; } namespace T { int dist[maxn]; int son[maxn][2]; ll add_tag[maxn],mul_tag[maxn]; void init() { dist[0]=-1; for(int i=1;i<=m;i++) add_tag[i]=0,mul_tag[i]=1; } void make_mul_tag(int u,ll v) { p[u].s*=v,add_tag[u]*=v,mul_tag[u]*=v; } void make_add_tag(int u,ll v) { p[u].s+=v,add_tag[u]+=v; } void push_down(int p) { if(mul_tag[p]!=1) { make_mul_tag(son[p][0],mul_tag[p]); make_mul_tag(son[p][1],mul_tag[p]); mul_tag[p]=1; } if(add_tag[p]) { make_add_tag(son[p][0],add_tag[p]); make_add_tag(son[p][1],add_tag[p]); add_tag[p]=0; } } int merge(int a,int b) { if(!a||!b)return a+b; if(p[a].s>p[b].s)swap(a,b); push_down(a); son[a][1]=merge(son[a][1],b); if(dist[son[a][1]]>dist[son[a][0]]) swap(son[a][1],son[a][0]); dist[a]=dist[son[a][1]]+1; return a; } int pop(int u) { push_down(u); int tmp=merge(son[u][0],son[u][1]); son[u][0]=son[u][1]=0; return tmp; } } void dfs(int u) { for(int P=now[u],V=to[P];P;P=pre[P],V=to[P]) dep[V]=dep[u]+1,dfs(V),rt[u]=T::merge(rt[u],rt[V]); while(rt[u]&&p[rt[u]].s<h[u]) { ans[u]++;p[rt[u]].ans=dep[p[rt[u]].c]-dep[u]; rt[u]=T::pop(rt[u]); } if(a[u])T::make_mul_tag(rt[u],v[u]); else T::make_add_tag(rt[u],v[u]); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++)h[i]=READ(); for(int i=2;i<=n;i++) { int f=read();add(f,i); a[i]=read(),v[i]=READ(); }T::init(); for(int i=1;i<=m;i++) { p[i].s=READ(),p[i].c=read(); rt[p[i].c]=T::merge(rt[p[i].c],i); }dep[1]=1;dfs(1); while(rt[1]) { p[rt[1]].ans=dep[p[rt[1]].c]; rt[1]=T::pop(rt[1]); } for(int i=1;i<=n;i++)printf("%d\n",ans[i]); for(int i=1;i<=m;i++)printf("%d\n",p[i].ans); return 0; }