BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆

Posted 鲸头鹳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆相关的知识,希望对你有一定的参考价值。

https://www.lydsy.com/JudgeOnline/problem.php?id=4003

感觉就是……普通的堆啊(暴论),因为这个堆是通过递归往右堆里加一个新堆或者新节点的,所以要始终保持右边的堆比左边的堆小一些以保证复杂度,大概因为这个所以也叫左偏树吧。

这个题我最开始看错题目了所以看板子的时候一头雾水满脑子都是“这个实现有问题吧”,然后又看了一遍题目发现没问题骑士就是往上走的。

这道题是把每个点建一个堆然后从叶子到根向上传递+去掉没法再往上的,复杂度大概是O(nlogn)?

技术分享图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=300010;
 9 long long read(){
10     long long x=0,f=1;char ch=getchar();
11     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
12     while(0<=ch&&ch<=9){ x=x*10+ch-0;ch=getchar(); }
13     return x*f;
14 }
15 int n,m;
16 long long h[maxn]={},k[maxn]={},b[maxn]={},s[maxn]={};
17 int fa[maxn]={},c[maxn]={};
18 int rt[maxn]={},ans1[maxn]={},ans2[maxn]={};
19 struct use{ int y,next; }e[maxn];
20 int head[maxn]={},dep[maxn]={},tot=0;
21 struct hp{ long long k,b,v; int dis,l,r; }t[maxn];
22 void init(int x,int y){
23     e[++tot].y=y;e[tot].next=head[x];head[x]=tot;
24 }
25 inline void Ad(int x,long long tk,long long tb){
26     t[x].k*=tk;
27     t[x].b=t[x].b*tk+tb;
28     t[x].v=t[x].v*tk+tb;
29 }
30 inline void downdata(int x){
31     if(t[x].l)Ad(t[x].l,t[x].k,t[x].b);;
32     if(t[x].r)Ad(t[x].r,t[x].k,t[x].b);
33     t[x].k=1;t[x].b=0;
34 }
35 int merge(int x,int y){
36     if(!x)return y;if(!y)return x;
37     downdata(x);downdata(y);
38     if(t[x].v>t[y].v)swap(x,y);
39     t[x].r=merge(t[x].r,y);
40     if(t[t[x].r].dis>t[t[x].l].dis)swap(t[x].r,t[x].l);
41     t[x].dis=t[t[x].r].dis+1;
42     return x;
43 }
44 void dfs(int x){
45     int y;
46     for(int i=head[x];i;i=e[i].next){
47         y=e[i].y;
48         dep[y]=dep[x]+1;
49         dfs(y);Ad(rt[y],k[y],b[y]);
50         rt[x]=merge(rt[x],rt[y]);
51     }
52     while(rt[x]&&t[rt[x]].v<h[x]){
53         downdata(rt[x]);ans1[x]++;
54         ans2[rt[x]]=dep[c[rt[x]]]-dep[x];
55         rt[x]=merge(t[rt[x]].l,t[rt[x]].r);
56     }
57 }
58 int main(){
59     n=read();m=read();
60     for(int i=1;i<=n;i++)h[i]=read();
61     for(int i=2;i<=n;i++){
62         fa[i]=read();init(fa[i],i);
63         k[i]=read();b[i]=read();
64         if(!k[i])k[i]=1;
65         else{k[i]=b[i];b[i]=0;}
66     }
67     for(int i=1;i<=m;i++){
68         s[i]=read();c[i]=read();
69         t[i].k=1; t[i].b=0; t[i].v=s[i];
70         rt[c[i]]=merge(rt[c[i]],i);
71     }dep[1]=1;
72     dfs(1);
73     while(rt[1]){
74         downdata(rt[1]);
75         ans2[rt[1]]=dep[c[rt[1]]];
76         rt[1]=merge(t[rt[1]].l,t[rt[1]].r);
77     }
78     for(int i=1;i<=n;i++)printf("%d\n",ans1[i]);
79     for(int i=1;i<=m;i++)printf("%d\n",ans2[i]);
80     return 0;
81 }
View Code

 

以上是关于BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4003JLOI2015城池攻占

[BZOJ4003][JLOI2015]城池攻占

bzoj4003[JLOI2015]城池攻占 可并堆

BZOJ4003 JLOI2015城池攻占

bzoj4003: [JLOI2015]城池攻占 左偏树

BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆