物流管理系统,简述seo和sem的区别与联系,做的好的音乐网站,二手房网站怎么做才能接到电话左偏树
算法浅析左偏树本质上是就是一个堆#xff0c;不过在堆的基础上新增了 “左偏” 的性质#xff0c;使得合并跟加快速.
思路上大致可以从 “合并 的角度想起.A - 可并堆 1板题#xff0c;直接上代码.#includebits/stdc.h
# define Maxn 100005
using na…左偏树算法浅析左偏树本质上是就是一个堆不过在堆的基础上新增了 “左偏” 的性质使得合并跟加快速.思路上大致可以从 “合并 的角度想起.A - 可并堆 1板题直接上代码.#includebits/stdc.h # define Maxn 100005 using namespace std; bool bz[Maxn]; int n,m,op,x,y,v,tot; struct Node{int fa,dist,l,r,v;}tr[Maxn]; int find(int x) { if(x!tr[x].fa) tr[x].fafind(tr[x].fa); return tr[x].fa; } int Merge(int x,int y) { if((!x)||(!y)) return xy; if(tr[x].vtr[y].v) swap(x,y); tr[x].rMerge(tr[x].r,y); if(tr[tr[x].l].disttr[tr[x].r].dist) swap(tr[x].l,tr[x].r); tr[x].disttr[tr[x].r].dist1; return x; } int main() { scanf(%d%d,n,m); for(int i1;in;i) { scanf(%d,v); tr[tot]{tot,0,0,0,v}; } while(m--) { scanf(%d,op); if(op1) { scanf(%d%d,x,y); if(bz[x]|bz[y]) continue; int f1find(x),f2find(y); if(f1f2) continue; tr[f1].fatr[f2].faMerge(f1,f2); } if(op2) { scanf(%d,x); if(bz[x]) {printf(-1\n);continue;} int f1find(x);bz[f1]1; printf(%d\n,tr[f1].v); if((!tr[f1].l)(!tr[f1].r)) continue; tr[f1].fatr[tr[f1].l].fatr[tr[f1].r].faMerge(tr[f1].l,tr[f1].r); } } return 0; }B - Monkey King也是板题不过要注意最后输出的是所有的最大。#includebits/stdc.h # define Maxn 100005 using namespace std; int n,m,v,x,y,tot,p[Maxn]; struct Node{int fa,l,r,dist,v,id;}tr[Maxn2]; int find(int x) { if(x!tr[x].fa) tr[x].fafind(tr[x].fa); return tr[x].fa; } int Merge(int x,int y) { if((!x)||(!y)) return xy; if(tr[x].vtr[y].v) swap(x,y); tr[x].rMerge(tr[x].r,y); if(tr[tr[x].l].disttr[tr[x].r].dist) swap(tr[x].l,tr[x].r); tr[x].disttr[tr[x].r].dist1; return x; } void clear() { for(int i1;itot;i) tr[i]{0,0,0,0,0,0}; tot0; } int main() { // freopen(my.out,w,stdout); while(~scanf(%d,n)) { for(int i1;in;i) { scanf(%d,v); tr[tot]{i,0,0,0,v,i},p[i]i; } scanf(%d,m); while(m--) { scanf(%d%d,x,y); int f1find(p[x]),f2find(p[y]); if(f1f2) {printf(-1\n);continue;} int newf1,newf2,Newf1,Newf2,RT; newf1tr[f1].fatr[tr[f1].l].fatr[tr[f1].r].faMerge(tr[f1].l,tr[f1].r); tr[tot]{tot,0,0,0,tr[f1].v/2,tr[f1].id},p[tr[f1].id]tot; Newf1tr[tot].fatr[newf1].faMerge(tot,newf1); newf2tr[f2].fatr[tr[f2].l].fatr[tr[f2].r].faMerge(tr[f2].l,tr[f2].r); tr[tot]{tot,0,0,0,tr[f2].v/2,tr[f2].id},p[tr[f2].id]tot; Newf2tr[tot].fatr[newf2].faMerge(tot,newf2); RTtr[Newf1].fatr[Newf2].faMerge(Newf1,Newf2); printf(%d\n,tr[RT].v); }clear(); } return 0; }C - 派遣显然在领导固定时人越多越好于是考虑从小到大依次选择然后删掉多余的.显然可用左偏树实现. 每个点最多进堆一次出堆一次时间复杂度O(nlogn)O(nlogn)O(nlogn).#includebits/stdc.h # define Maxn 100005 # define ll long long using namespace std; int n,m,srt[Maxn],RT,cnt; int head[Maxn],tot1; ll ans; struct Edge{int to,next;}e[Maxn]; struct Node{int fa,c,l;}a[Maxn]; struct Tree{int fa,l,r,dist,sz,v;ll sum;}tr[Maxn]; void add(int u,int v) { e[tot]{v,head[u]}; head[u]tot; } int find(int x) { if(x!tr[x].fa) tr[x].fafind(tr[x].fa); return tr[x].fa; } int Merge(int x,int y) { if((!x)||(!y)) return xy; if(tr[x].vtr[y].v) swap(x,y); tr[x].rMerge(tr[x].r,y); if(tr[tr[x].l].disttr[tr[x].r].dist) swap(tr[x].l,tr[x].r); tr[x].disttr[tr[x].r].dist1; tr[x].sztr[tr[x].l].sztr[tr[x].r].sz1; tr[x].sumtr[tr[x].l].sumtr[tr[x].r].sumtr[x].v; return x; } int Del(int x) { int rttr[x].fatr[tr[x].l].fatr[tr[x].r].faMerge(tr[x].l,tr[x].r); return rt; } void dfs(int rt) { for(int ihead[rt];i;ie[i].next) { dfs(e[i].to); srt[rt]tr[srt[rt]].fatr[srt[e[i].to]].faMerge(srt[rt],srt[e[i].to]); } while(tr[srt[rt]].summ) srt[rt]Del(srt[rt]); // printf(%d: %d\n,rt,tr[srt[rt]].sz); ansmax(ans,1ll*a[rt].l*tr[srt[rt]].sz); } int main() { scanf(%d%d,n,m); for(int i1;in;i) { scanf(%d%d%d,a[i].fa,a[i].c,a[i].l); tr[cnt]{cnt,0,0,0,1,a[i].c,a[i].c},srt[i]cnt; if(!a[i].fa) RTi; else add(a[i].fa,i); }dfs(RT); printf(%lld\n,ans); return 0; }D - Sequence (Day1)应该说是最有价值的一题了.首先先做一个经典tricktricktrick将每个aia_iai−i-i−i从而将严格单调变成不降.然后考虑特殊情形例如单减显然要全取中位数.那么我们将所有极大单减分量先组起来再去考虑如何将几个分量糅合从而满足题目的不降条件.画图易证:::如果不满足条件那么直接往前糅合一定最优.具体实现考虑用栈每次加入就将他不断向前糅合糅合用左偏树实现.#includebits/stdc.h # define Maxn 1000005 # define ll long long using namespace std; int n,a[Maxn],b[Maxn],tot; int s[Maxn],top,id[Maxn],All[Maxn]; ll ans; struct Node{int fa,l,r,dist,sz,v;}tr[Maxn]; int Merge(int x,int y) { if((!x)||(!y)) return xy; if(tr[x].vtr[y].v) swap(x,y); tr[x].rMerge(tr[x].r,y); if(tr[tr[x].l].disttr[tr[x].r].dist) swap(tr[x].l,tr[x].r); tr[x].disttr[tr[x].r].dist1; tr[x].sztr[tr[x].l].sztr[tr[x].r].sz1; return x; } int Del(int x) { int rttr[x].fatr[tr[x].l].fatr[tr[x].r].faMerge(tr[x].l,tr[x].r); return rt; } int L[Maxn],R[Maxn]; int main() { scanf(%d,n); for(int i1;in;i) { scanf(%d,a[i]),a[i]-i; tr[tot]{tot,0,0,0,1,a[i]}; int nowtot,sum1,sli; while(toptr[s[top]].vtr[now].v) { nowtr[now].fatr[s[top]].faMerge(now,s[top]); sumAll[top--]; while(tr[now].sz(sum1)/2) nowDel(now); }s[top]now,All[top]sum; } int k1; for(int i1;itop;i) { for(int j1;jAll[i];j) { b[k]tr[s[i]].v; ansabs(a[k-1]-b[k-1]); } } printf(%lld\n,ans); for(int i1;in;i) printf(%d\n,b[i]i); return 0; }E - 城池攻占维护每个城池上的骑士然后就没了.#includebits/stdc.h # define Maxn 300005 # define ll long long using namespace std; int n,m,srt[Maxn],cnt; int head[Maxn],tot1; struct Edge{int to,next;}e[Maxn]; struct Node{int fa,a;ll h,v;}a[Maxn]; struct Tree{int fa,l,r,dist,sz,id;ll v,lz11,lz20;}tr[Maxn1]; void add(int u,int v) { e[tot]{v,head[u]}; head[u]tot; } int s[Maxn],c[Maxn],dep[Maxn],sum1[Maxn],sum2[Maxn]; void Put(int rt,ll v1,ll v2) { tr[rt].vtr[rt].v*v1v2; tr[rt].lz1*v1,tr[rt].lz2*v1,tr[rt].lz2v2; } void Push(int rt) { Put(tr[rt].l,tr[rt].lz1,tr[rt].lz2); Put(tr[rt].r,tr[rt].lz1,tr[rt].lz2); tr[rt].lz11,tr[rt].lz20; } int Merge(int x,int y) { Push(x),Push(y); if((!x)||(!y)) return xy; if(tr[x].vtr[y].v) swap(x,y); tr[x].rMerge(tr[x].r,y); if(tr[tr[x].l].disttr[tr[x].r].dist) swap(tr[x].l,tr[x].r); tr[x].disttr[tr[x].r].dist1; tr[x].sztr[tr[x].l].sztr[tr[x].r].sz1; return x; } int Del(int x) { int rttr[x].fatr[tr[x].l].fatr[tr[x].r].faMerge(tr[x].l,tr[x].r); return rt; } void dfs(int rt) { for(int ihead[rt];i;ie[i].next) { dep[e[i].to]dep[rt]1,dfs(e[i].to); srt[rt]tr[srt[rt]].fatr[srt[e[i].to]].faMerge(srt[rt],srt[e[i].to]); } while(tr[srt[rt]].sztr[srt[rt]].va[rt].h) { sum1[rt],sum2[tr[srt[rt]].id]dep[c[tr[srt[rt]].id]]-dep[rt]; srt[rt]Del(srt[rt]); } if(a[rt].a0) Put(srt[rt],1,a[rt].v); else Put(srt[rt],a[rt].v,0); } int main() { scanf(%d%d,n,m),cntn; for(int i1;in;i) scanf(%lld,a[i].h); for(int i2;in;i) { scanf(%d%d%lld,a[i].fa,a[i].a,a[i].v); add(a[i].fa,i); } for(int i1;im;i) { scanf(%d%d,s[i],c[i]),cnt; tr[cnt].fatr[cnt].ltr[cnt].rtr[cnt].dist0,tr[cnt].sz1,tr[cnt].idi,tr[cnt].vs[i]; srt[c[i]]tr[srt[c[i]]].fatr[cnt].faMerge(srt[c[i]],cnt); }dfs(1); while(tr[srt[1]].sz) { sum2[tr[srt[1]].id]dep[c[tr[srt[1]].id]]1; srt[1]Del(srt[1]); } for(int i1;in;i) printf(%d\n,sum1[i]); for(int i1;im;i) printf(%d\n,sum2[i]); return 0; }总结左偏树主要的下手点应是 “合并”思路上讲究的是 “循序渐进”逐步想到 “合并”.代码需要注意的BUG(1). 删除节点时的原根节点父亲赋值应赋成新根.(2). 若有懒标记一定要在最开始下放.