亿些模板【数据结构】

文章目录

    • 前言
  • 数据结构模板
    • 并查集
    • 带权并查集
    • hash表
    • RMQ
    • 线段树
    • 树状数组
    • 树状数组区间修改版
    • 分块
    • 主席树
    • 有旋Treap
    • Splay
    • 替罪羊树
    • 文艺平衡树-Splay
    • 点分治
    • 树链剖分
    • 可持久化并查集
    • LCT
    • 左偏树

前言

因为老是懒得打模板的时候老是扣不到自己的标(因为之前的都打得太丑了),所以导致我十分的不爽。便打算开一个模板库。会不断更新的


数据结构模板

并查集

int find(int x)//并查集
{return f[x]==x?x:(f[x]=find(f[x]));}
void unionn(int x,int y)//连接
{int fa=find(x),fb=find(y);if(fa<fb) f[fa]=fb;else f[fb]=fa;
}

带权并查集

int find(int x)
{if (father[x]==x) {return x;}else{int fa=father[x];father[x]=find(father[x]);far[x]=far[x]+far[fa]0;return father[x];}
}
void unionn(int x,int y,int w)
{int fa=find(x),fb=find(y);father[fb]=fa;far[fb]=far[x]-far[y]+w;
}

#include<cstdio>
#include<algorithm>
using namespace std;
int a[1000010],num,x,n,v;
void up(int x)
{int t;while (x>1 && a[x]<a[x/2]){t=a[x];a[x]=a[x/2];a[x/2]=t;x/=2;}
}
void down(int x)
{int t,y;while (x*2<=num && a[x]>a[x*2] || x*2+1<=num && a[x]>a[x*2+1]){y=x*2;if (x*2+1<=num && a[x*2]>a[x*2+1]) y++;t=a[x];a[x]=a[y];a[y]=t;x=y;}
}
void insert(int x)
{a[++num]=x;up(num);}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&v);if(v==1){scanf("%d",&x);a[++num]=x;up(num);}else if(v==2){printf("%d\n",a[1]);}else{swap(a[1],a[num]);num--;down(1);}}
}

hash表

int n,s,hash[maxn+10],a[5001];
bool v[maxn+10];
int hashmath(int x)
{return (x%maxn+maxn)%maxn;}
int locate(int x)//查找位置
{int i=0,w=hashmath(x);while (i<maxn&&v[(w+i)%maxn]&&hash[(w+i)%maxn]!=x)i++;return (w+i)%maxn;
}
void ins(int x)//插入
{int w=locate(x);hash[w]=x;v[w]=true;
}
bool find(int x)//查找
{int w=locate(x);if (hash[w]==x&&v[w]) return true;else return false;
}

RMQ

#include<cstdio>
#include<cmath>
//开log用
#include<iostream>
using namespace std;
int f[100001][21],n,m,z,x,y;
int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)scanf("%d",&f[i][0]);//输出for (int j=1;(1<<j)<=n;j++)for (int i=1;i+(1<<j)-1<=n;i++){f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);//动态转移}for (int i=1;i<=m;i++){scanf("%d%d",&x,&y);z=(int)(log(y-x+1)/log(2));//计算xprintf("%d\n",max(f[x][z],f[y+1-(1<<z)][z]));//输出}
}

线段树

#include<cstdio>
#include<algorithm>
#define N 100010
#define ll long long
using namespace std;
struct treenode{int l,r;ll val,lazy;
}t[N*4];
int n,m,l,r;
ll x;
char c[2];
void build(int x,int l,int r)//建树
{t[x].l=l;t[x].r=r;if(l==r){scanf("%lld",&t[x].val);return;}int mid=(l+r)>>1;build(x*2,l,mid);build(x*2+1,mid+1,r);t[x].val=t[x*2].val+t[x*2+1].val;
}
void downdata(int x)//下传标记
{if(t[x].lazy){t[x*2].lazy+=t[x].lazy;t[x*2].val+=t[x].lazy*(t[x*2].r-t[x*2].l+1);t[x*2+1].lazy+=t[x].lazy;t[x*2+1].val+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1);t[x].lazy=0;}
}
void change(int x,int l,int r,ll num)//区间修改
{if(t[x].l==l&&t[x].r==r){t[x].val+=num*(t[x].r-t[x].l+1);t[x].lazy+=num;return;}downdata(x);int mid=(t[x].l+t[x].r)>>1;if(r<=mid) change(x*2,l,r,num);else if(l>mid) change(x*2+1,l,r,num);else change(x*2,l,mid,num),change(x*2+1,mid+1,r,num);t[x].val=t[x*2].val+t[x*2+1].val;
}
ll find(int x,int l,int r)//区间查询
{if(t[x].l==l&&t[x].r==r)return t[x].val;downdata(x);int mid=(t[x].l+t[x].r)>>1;if(r<=mid) return find(x*2,l,r);else if(l>mid) return find(x*2+1,l,r);else return find(x*2,l,mid)+find(x*2+1,mid+1,r);    
}
int main()
{scanf("%d%d",&n,&m);build(1,1,n);for(int i=1;i<=m;i++){scanf("%s %d %d",c,&l,&r);if(c[0]=='Q') printf("%lld\n",find(1,l,r));else{scanf("%lld",&x);change(1,l,r,x);}}
}

树状数组

int lowbit(int x)
{return x&(x^(x-1));}
void change(int x,int num)//修改
{int i=x;while(i<=82000){c[i]+=num;i+=lowbit(i);}
}
int getsum(int x)//求值
{int sum=0;while (x>0){sum+=c[x];x-=lowbit(x);}return sum;
}

树状数组区间修改版

#include<cstdio>
#include<algorithm>
#include<iostream>
#define lobit(x) x&-x
using namespace std;
long long t[2][100010],x,a[100010],sum[100010];
int n,m,l,r;
void add(int k,int x,int num)//修改
{while(x<=n){t[k][x]+=num;x+=lobit(x);}
}
long long ask(int k,int x)//查询
{long long sum=0;while(x>0){sum+=t[k][x];x-=lobit(x);}return sum;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%lld",&a[i]);sum[i]=sum[i-1]+a[i];}for(int i=1;i<=m;i++){char c[2];scanf("%s %d %d",c,&l,&r);if(c[0]=='Q'){long long ans=sum[r]+(r+1)*ask(0,r)-ask(1,r);ans-=sum[l-1]+l*ask(0,l-1)-ask(1,l-1);//查询printf("%lld\n",ans);}else{scanf("%d",&x);add(0,l,x);add(0,r+1,-x);add(1,l,l*x);add(1,r+1,-(r+1)*x);//修改}}
}

分块

#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
#define N 100010
using namespace std;
ll a[N],sum[N],add[N];
int L[N],R[N],d;
int pos[N];
int n,m,t,l,r;
char op[3];
void change(int l,int r,long long d)
{int p=pos[l],q=pos[r];if(p==q){for(int i=l;i<=r;i++) a[i]+=d;sum[p]+=d*(r-l+1);}//全都在一块中else{for(int i=p+1;i<=q-1;i++) add[i]+=d;//维护中间段落for(int i=l;i<=R[p];i++) a[i]+=d;sum[p]+=d*(R[p]-l+1);for(int i=L[q];i<=r;i++) a[i]+=d;sum[q]+=d*(r-L[q]+1);//暴力局部修改}
}
ll ask(int l,int r)
{int p=pos[l],q=pos[r];ll ans=0;if(p==q){for(int i=l;i<=r;i++) ans+=a[i];ans+=add[p]*(r-l+1);}//全部都在一块中else{for(int i=p+1;i<=q-1;i++)ans+=sum[i]+add[i]*(R[i]-L[i]+1);//累加中间段落for(int i=l;i<=R[p];i++) ans+=a[i];ans+=add[p]*(R[p]-l+1);for(int i=L[q];i<=r;i++) ans+=a[i];ans+=add[q]*(r-L[q]+1);//暴力局部累加}return ans;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);t=sqrt(n);for(int i=1;i<=t;i++){L[i]=(i-1)*t+1;R[i]=i*t;}//标记每块左右if(R[t]<n) t++,L[t]=R[t-1]+1,R[t]=n;//补足尾部for(int i=1;i<=t;i++)for(int j=L[i];j<=R[i];j++){pos[j]=i;//表示属于哪个块sum[i]+=a[j];//计算段落和}for(int i=1;i<=m;i++){scanf("%s %d %d",op,&l,&r);if(op[0]=='C'){scanf("%d",&d);change(l,r,d);}else printf("%lld\n",ask(l,r));}
}

主席树

#include<cstdio>
#include<algorithm>
#define MN 200010
using namespace std;
struct tnode{int w,l,r,ls,rs;
}t[MN<<5];
int n,m,x,y,k,a[MN],b[MN],root[MN],num,q,w;
int build(int l,int r)//建立一棵空树
{int k=++num;t[k].l=l,t[k].r=r;if (l==r) return k;int mid=(l+r)>>1;t[k].ls=build(l,mid);t[k].rs=build(mid+1,r);//左右分区return k;//返回编号
}
int addt(int k,int z)//建立一条新链
{int nb=++num;t[nb]=t[k];t[nb].w++;//动态开点if (t[k].l==z&&t[k].r==z) return nb;//到达节点int mid=(t[k].l+t[k].r)>>1;if (z<=mid) t[nb].ls=addt(t[k].ls,z);else t[nb].rs=addt(t[k].rs,z);//建立下一个节点return nb;
}
int query(int k1,int k2,int k)//前缀和询问区间
{if (t[k1].l==t[k1].r) return t[k1].l;w=t[t[k2].ls].w-t[t[k1].ls].w;//计算左子树在这个区间内的数字数量if (k<=w) return query(t[k1].ls,t[k2].ls,k);else return query(t[k1].rs,t[k2].rs,k-w);//向下询问
}
int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];sort(b+1,b+1+n);//排序(离散化1)int q=unique(b+1,b+1+n)-b-1;//去重(离散化)root[0]=build(1,q);//建立空树for (int i=1;i<=n;i++){int te=lower_bound(b+1,b+1+q,a[i])-b;//二分寻找原来的位置root[i]=addt(root[i-1],te);//建立一条链}for (int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&k);printf("%d\n",b[query(root[x-1],root[y],k)]);//询问区间}
}

有旋Treap

#include<cstdio>
#include<algorithm>
#define INF 2147483647/3
#define N 100010
using namespace std;
int n,root;
struct Treap_node{int l[N],r[N];int val[N],dat[N];int cnt[N],size[N];int tot;int New(int new_val){val[++tot]=new_val;dat[tot]=rand();cnt[tot]=size[tot]=1;return tot;}void Updata(int p){size[p]=size[l[p]]+size[r[p]]+cnt[p];}void Build(){New(-INF);New(INF);root=1;r[1]=2;Updata(root);}int GetRankByVal(int p,int num){if(p==0) return 0;if(num==val[p]) return size[l[p]]+1;if(num<val[p]) return GetRankByVal(l[p],num);return GetRankByVal(r[p],num)+size[l[p]]+cnt[p];}int GetValByRank(int p,int rank){if (p==0) return INF;if(size[l[p]]>=rank) return GetValByRank(l[p],rank);if(size[l[p]]+cnt[p]>=rank) return val[p];return GetValByRank(r[p],rank-size[l[p]]-cnt[p]);}void zig(int &p){int q=l[p];l[p]=r[q];r[q]=p;p=q;Updata(r[p]);Updata(p);}void zag(int &p){int q=r[p];r[p]=l[q];l[q]=p;p=q;Updata(l[p]);Updata(p);}void Insert(int &p,int num){if(p==0){p=New(num);return;}if(num==val[p]){cnt[p]++;Updata(p);return;}if(num<val[p]){Insert(l[p],num);if(dat[p]<dat[l[p]]) zig(p);}else{Insert(r[p],num);if(dat[p]<dat[r[p]]) zag(p);}Updata(p);}int GetPre(int num){int ans=1;int p=root;while(p){if(num==val[p]){if(l[p]>0){p=l[p];while(r[p]>0) p=r[p];ans=p;}break;}if(val[p]<num&&val[p]>val[ans]) ans=p;p=num<val[p]?l[p]:r[p];}return val[ans];}int GetNext(int num){int ans=2;int p=root;while(p){if(num==val[p]){if(r[p]>0){p=r[p];while(l[p]>0) p=l[p];ans=p;}break;}if(val[p]>num&&val[p]<val[ans]) ans=p;p=num<val[p]?l[p]:r[p];}return val[ans];}void Remove(int &p,int num){if(p==0) return;if(num==val[p]){if(cnt[p]>1){cnt[p]--;Updata(p);return;}if(l[p]||r[p]){if(r[p]==0||dat[l[p]]>dat[r[p]])zig(p),Remove(r[p],num);elsezag(p),Remove(l[p],num);Updata(p);}else p=0;return;}num<val[p]?Remove(l[p],num):Remove(r[p],num);Updata(p);}
}a;
int main()
{a.Build();scanf("%d",&n);while(n--){int opt,x;scanf("%d%d",&opt,&x);switch(opt){case 1:a.Insert(root,x);break;case 2:a.Remove(root,x);break;case 3:printf("%d\n",a.GetRankByVal(root,x)-1);break;case 4:printf("%d\n",a.GetValByRank(root,x+1));break;case 5:printf("%d\n",a.GetPre(x));break;case 6:printf("%d\n",a.GetNext(x));break;}}
}

Splay

#include<cstdio>
#include<algorithm>
#define INF 2100000000
#define N 100010
using namespace std;
struct splay{int v[N],father[N];int l[N],r[N];int sum[N],recy[N];int n,points;#define root r[0]void Updata(int x){sum[x]=sum[l[x]]+sum[r[x]]+recy[x];}int Identify(int x){return l[father[x]]==x?0:1;}void Connect(int x,int f,int son){father[x]=f;if(son) r[f]=x;else l[f]=x;}void Rotate(int x){int y=father[x];int mroot=father[y];int mrootson=Identify(y);int yson=Identify(x);int B=(yson?l[x]:r[x]);Connect(B,y,yson);Connect(y,x,(yson^1));Connect(x,mroot,mrootson);Updata(y);Updata(x);}void Splay(int at,int to){to=father[to];while(father[at]!=to){int up=father[at];if(father[up]==to) Rotate(at);else if(Identify(up)==Identify(at)){Rotate(up);Rotate(at);}else{Rotate(at);Rotate(at);}}}int CrePoint(int vs,int fathers){n++;v[n]=vs;father[n]=fathers;sum[n]=recy[n]=1;return n;}void Destory(int x){v[x]=l[x]=r[x]=sum[x]=father[x]=recy[x]=0;if(x==n)n--;}int getroot(){return root;}int FindVal(int vs){int now=root;if(!now) return 0;while(true){if(v[now]==vs){Splay(now,root);return root;}int next=vs<v[now]?0:1;if(!(next?r[now]:l[now])) return 0;now=(next?r[now]:l[now]);}}int Build(int vs){points++;if(!n){root=1;CrePoint(vs,0);}else{int now=root;while(1){sum[now]++;if(vs==v[now]){recy[now]++;return now;}int next=vs<v[now]?0:1;if(!(next?r[now]:l[now])){CrePoint(vs,now);if(next) r[now]=n;else l[now]=n;return n;}now=next?r[now]:l[now];}}return 0;}void Insert(int vs){int add=Build(vs);Splay(add,root);}void Remove(int vs){int deal=FindVal(vs);if(!deal) return;points--;if(recy[deal]>1){recy[deal]--;sum[deal]--;return;}if(!l[deal]){root=r[deal];father[root]=0;}else{int lef=l[deal];while(r[lef]) lef=r[lef];Splay(lef,l[deal]);int rig=r[deal];Connect(rig,lef,1);Connect(lef,0,1);Updata(lef);}Destory(deal);}int GetRankByVal(int vs){int now=root;if(!now) return 0;while((vs>v[now]?r[now]:l[now])&&vs!=v[now])now=(vs>v[now]?r[now]:l[now]);Splay(now,root);return sum[l[root]];}int GetValByRank(int x){if(x>points) return -INF;int now=root;while(1){int minused=sum[now]-sum[r[now]];if(x>sum[l[now]]&&x<=minused) break;if(x<minused)now=l[now];else{x-=minused;now=r[now];}}Splay(now,root);return v[now];}int Upper(int vs){int now=root;int result=INF;while(now){if(v[now]>vs&&v[now]<result) result=v[now];if(vs<v[now]) now=l[now];else now=r[now];}return result;}int Lower(int vs){int now=root;int result=-INF;while(now){if(v[now]<vs&&v[now]>result) result=v[now];if(vs>v[now]) now=r[now];else now=l[now];}return result;}#undef root
}a;
int main(){freopen("testdata.in","r",stdin);freopen("data.out","w",stdout);a.Insert(-INF);a.Insert(INF);int m;scanf("%d",&m);while(m--){int opt,x;scanf("%d%d",&opt,&x);if(opt==1) a.Insert(x);if(opt==2) a.Remove(x);if(opt==3) printf("%d\n",a.GetRankByVal(x));if(opt==4) printf("%d\n",a.GetValByRank(x+1));if(opt==5) printf("%d\n",a.Lower(x));if(opt==6) printf("%d\n",a.Upper(x));}
}

替罪羊树

#include<cstdio>
#include<algorithm>
#include<cctype>
#define alpha 0.8
#define N 100010
using namespace std;
inline int read(){int x(0),sign(0);char ch=getchar();while(!isdigit(ch)){if(ch=='-') sign=1;ch=getchar();}while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();return sign?-x:x;
}
struct goat_Tree{int l[N],r[N],size[N],val[N],valid[N],total[N];int cur[N],memory[N];bool exist[N];int root,poi,pool,cnt;void ReMemory(){for(int i=N-10;i>=1;i--)memory[++pool]=i;}bool Isbad(int now){if((double)valid[now]*alpha<=(double)max(valid[l[now]],valid[r[now]]))return true;else return false;}void Beat(int now){if(!now) return;Beat(l[now]);if(exist[now]) cur[++poi]=now;else memory[++pool]=now;Beat(r[now]);}void New(int x){l[x]=r[x]=0;total[x]=valid[x]=1;}void Build(int ls,int rs,int &now){int mid=(ls+rs)>>1;now=cur[mid];if(ls==rs){New(now);return;}if(ls<mid) Build(ls,mid-1,l[now]);else l[now]=0;Build(mid+1,rs,r[now]);total[now]=total[l[now]]+total[r[now]]+1;valid[now]=valid[l[now]]+valid[r[now]]+1;}void ReBuild(int &now){poi=0;Beat(now);if(poi) Build(1,poi,now);else now=0;}int GetRankByVal(int k){int now=root;int ans=1;while(now){if(val[now]>=k) now=l[now];else{ans+=valid[l[now]]+exist[now];now=r[now];}}return ans;}int GetValByRank(int k){int now=root;while(now){if(exist[now]&&valid[l[now]]+1==k)return val[now];if(valid[l[now]]>=k) now=l[now];else{k-=valid[l[now]]+exist[now];now=r[now];}}}void Insert(int &now,int num){if(!now){now=memory[pool--];val[now]=num;New(now);exist[now]=1;return;}total[now]++;valid[now]++;if(val[now]>=num) Insert(l[now],num);else Insert(r[now],num);if(Isbad(now))ReBuild(now);}void Remove_z(int &now,int tar){if(exist[now]&&valid[l[now]]+1==tar){exist[now]=0;valid[now]--;return;}valid[now]--;if(valid[l[now]]+exist[now]>=tar)Remove_z(l[now],tar);else Remove_z(r[now],tar-valid[l[now]]-exist[now]);}void Remove(int tar){Remove_z(root,GetRankByVal(tar));if((double)total[root]*alpha>valid[root])ReBuild(root);}
}a;
int main()
{int opt,x,m;a.ReMemory();scanf("%d",&m);while(m--){opt=read();x=read();if(opt==1) a.Insert(a.root,x);if(opt==2) a.Remove(x);if(opt==3) printf("%d\n",a.GetRankByVal(x));if(opt==4) printf("%d\n",a.GetValByRank(x));if(opt==5) printf("%d\n",a.GetValByRank(a.GetRankByVal(x)-1));if(opt==6) printf("%d\n",a.GetValByRank(a.GetRankByVal(x+1)));}
}

文艺平衡树-Splay

#include<cstdio>
#include<algorithm>
#define INF 2100000000
#define N 100010
using namespace std;
struct splay{int v[N],father[N],root;int l[N],r[N];int sum[N],mark[N];int n,points;void Updata(int x){sum[x]=sum[l[x]]+sum[r[x]]+1;}void Downdata(int x){if(mark[x]){mark[l[x]]^=1;mark[r[x]]^=1;mark[x]=0;swap(l[x],r[x]);}}void New(int x,int vs,int fa){l[x]=r[x]=0;sum[x]=1;v[x]=vs;father[x]=fa;}void Rotate(int x){int y=father[x];int z=father[y];int k=r[y]==x;if(r[z]==y) r[z]=x;else l[z]=x;father[x]=z;if(k) r[y]=l[x];else l[y]=r[x];father[k?l[x]:r[x]]=y;if(k) l[x]=y;else r[x]=y;father[y]=x;Updata(y);Updata(x);}void Splay(int at,int to){while(father[at]!=to){int y=father[at];int z=father[y];if(z!=to)(r[z]==y)^(r[z]==at)?Rotate(at):Rotate(y);Rotate(at);}if(to==0)root=at;}void Insert(int x){int now=root,ff=0;while(now)ff=now,now=(x>v[now]?r[now]:l[now]);now=++n;if(ff&&x>v[now]) r[ff]=now;else if(ff) l[ff]=now;New(now,x,ff);Splay(now,0);}int GetValByRank(int k){int now=root;while(1){Downdata(now);if(sum[l[now]]>=k) now=l[now];else if(sum[l[now]]+1==k) return now;else k-=sum[l[now]]+1,now=r[now];}}void Work(int ls,int rs){ls=GetValByRank(ls);rs=GetValByRank(rs+2);Splay(ls,0);Splay(rs,ls);mark[l[r[root]]]^=1;}void Write(int x,int mn){Downdata(x);if(l[x]) Write(l[x],mn);if(v[x]>1&&v[x]<mn+2) printf("%d ",v[x]-1);if(r[x]) Write(r[x],mn);}
}a;
int main(){//freopen("testdata.in","r",stdin);//freopen("data.out","w",stdout);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n+2;i++)a.Insert(i);while(m--){int l,r;scanf("%d%d",&l,&r);a.Work(l,r);}a.Write(a.root,n);
}

点分治

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100010
#define inf 10000000
using namespace std;
struct node{int to,next,w;
}a[N*2];
int n,m,que[1010],ok[inf],tot,sum,num,q[N];
int root,siz[N],f[N],ls[N],st[N],dis[N]; 
int lon[inf];
bool v[N];
void addl(int x,int y,int w)
{a[++tot].to=y;a[tot].next=ls[x];a[tot].w=w;ls[x]=tot;
}
void groot(int x,int fa)
{siz[x]=1;f[x]=0;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa||v[y]) continue;groot(y,x);siz[x]+=siz[y];f[x]=max(f[x],siz[y]);}f[x]=max(f[x],sum-siz[x]);if(f[x]<f[root]) root=x;
}
void get_dis(int x,int fa)
{st[++num]=dis[x];for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa||v[y]) continue;dis[y]=dis[x]+a[i].w;get_dis(y,x);}
}
void calc(int x)
{int p=0;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(v[y]) continue;num=0;dis[y]=a[i].w;get_dis(y,x);for(int j=num;j;j--)for(int k=1;k<=m;k++)ok[k]|=lon[que[k]-st[j]];for(int j=num;j;j--)q[++p]=st[j],lon[st[j]]=1;}for(int i=1;i<=p;i++)lon[q[i]]=0;
}
void solve(int x)
{v[x]=lon[0]=1;calc(x);for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(v[y]) continue;sum=siz[y];f[root=0]=n;groot(y,0);solve(y);}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int x,y,w;scanf("%d%d%d",&x,&y,&w);addl(x,y,w);addl(y,x,w);}for(int i=1;i<=m;i++)scanf("%d",&que[i]);f[0]=n;sum=n;groot(1,0);solve(root);for(int i=1;i<=m;i++)if(ok[i]) printf("AYE\n");else printf("NAY\n");
}

树链剖分

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200000;
int tot,cnt,n,m,s,p,ls[N],pw[N],id[N];
int siz[N],dep[N],f[N],son[N],seg[N],top[N];
struct treenode{int l,r,lazy,val;
};
struct LineTree{treenode t[N*2];void build(int x,int l,int r){t[x].l=l;t[x].r=r;if(l==r){t[x].val=pw[id[l]]%p;return;}int mid=(l+r)>>1;build(x*2,l,mid);build(x*2+1,mid+1,r);t[x].val=(t[x*2].val+t[x*2+1].val)%p;}void downdata(int x){if(t[x].lazy){(t[x*2].lazy+=t[x].lazy)%=p;(t[x*2].val+=t[x].lazy*(t[x*2].r-t[x*2].l+1))%=p;(t[x*2+1].lazy+=t[x].lazy)%=p;(t[x*2+1].val+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1))%=p;t[x].lazy=0;}}void change(int x,int l,int r,int num){if(t[x].l==l&&t[x].r==r){(t[x].val+=num*(t[x].r-t[x].l+1))%=p;(t[x].lazy+=num)%=p;return;}downdata(x);int mid=(t[x].l+t[x].r)>>1;if(r<=mid) change(x*2,l,r,num);else if(l>mid) change(x*2+1,l,r,num);else change(x*2,l,mid,num),change(x*2+1,mid+1,r,num);t[x].val=(t[x*2].val+t[x*2+1].val)%p;}int find(int x,int l,int r){if(t[x].l==l&&t[x].r==r)return t[x].val;downdata(x);int mid=(t[x].l+t[x].r)>>1;if(r<=mid) return find(x*2,l,r);else if(l>mid) return find(x*2+1,l,r);else return (find(x*2,l,mid)+find(x*2+1,mid+1,r))%p;    }
}LT;
struct edge_node{int to,next;
}a[N*2];
void addl(int x,int y)
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dfs1(int x,int fa)
{siz[x]=1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa) continue;dep[y]=dep[x]+1;f[y]=x;dfs1(y,x);siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}
}
void dfs2(int x,int fa)
{seg[x]=++cnt;id[cnt]=x;if(son[x]){top[son[x]]=top[x];dfs2(son[x],x);}for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa||y==son[x]) continue;top[y]=y;dfs2(y,x);}
}
void path_change(int x,int y,int z)
{while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);LT.change(1,seg[top[x]],seg[x],z);x=f[top[x]];}if(dep[x]>dep[y]) swap(x,y);LT.change(1,seg[x],seg[y],z);return;
}
int path_ask(int x,int y)
{int ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);(ans+=LT.find(1,seg[top[x]],seg[x]))%=p;x=f[top[x]];}if(dep[x]>dep[y]) swap(x,y);(ans+=LT.find(1,seg[x],seg[y]))%=p;return ans;
}
int main()
{scanf("%d%d%d%d",&n,&m,&s,&p);for(int i=1;i<=n;i++)scanf("%d",&pw[i]);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dfs1(s,0);top[s]=s;dfs2(s,0);LT.build(1,1,n);for(int i=1;i<=m;i++){int t,x,y,z;scanf("%d%d",&t,&x);if(t==1){scanf("%d%d",&y,&z);path_change(x,y,z);}if(t==2){scanf("%d",&y);printf("%d\n",path_ask(x,y));}if(t==3){scanf("%d",&z);LT.change(1,seg[x],seg[x]+siz[x]-1,z);}if(t==4){printf("%d\n",LT.find(1,seg[x],seg[x]+siz[x]-1));}}
}

可持久化并查集

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+100;
struct Tree_node{int ls,rs,l,r,deep,fa;
};
int n,m,cnt,root[N],edt;
struct Keep_tree{Tree_node t[N*40];void Build(int &x,int l,int r){x=++cnt;t[x].l=l;t[x].r=r;if(l==r){t[x].fa=l;return;}int mid=(t[x].l+t[x].r)/2;Build(t[x].ls,l,mid);Build(t[x].rs,mid+1,r);}Tree_node Query(int x,int pos){if(t[x].l==t[x].r)return t[x];if(pos<=t[t[x].ls].r) return Query(t[x].ls,pos);return Query(t[x].rs,pos);}void Insert(int x,int &y,int pos,int nef){y=++cnt;t[y]=t[x];if(t[x].l==t[x].r){t[y].fa=nef;return;}if(pos<=t[t[x].ls].r) Insert(t[x].ls,t[y].ls,pos,nef);else Insert(t[x].rs,t[y].rs,pos,nef);}void add(int x,int pos){if(t[x].l==t[x].r){t[x].deep++;return;}if(pos<=t[t[x].ls].r) add(t[x].ls,pos);else add(t[x].rs,pos);}
}Tree;
Tree_node find_fa(int ed,int x)
{Tree_node Fa=Tree.Query(root[ed],x);if(x==Fa.fa) return Fa;return find_fa(ed,Fa.fa);
}
void unionn(int x,int y)
{Tree_node Fa=find_fa(edt-1,x),Fb=find_fa(edt-1,y);if(Fa.fa==Fb.fa) return;if(Fa.deep<Fb.deep) swap(Fa,Fb);Tree.Insert(root[edt-1],root[edt],Fb.fa,Fa.fa);if(Fa.deep==Fb.deep)Tree.add(root[edt],Fa.fa);
}
int main()
{scanf("%d%d",&n,&m);Tree.Build(root[0],1,n);for(int i=1;i<=m;i++){int op,x,y;scanf("%d",&op);++edt;root[edt]=root[edt-1];if(op==1){scanf("%d%d",&x,&y);unionn(x,y);}if(op==2){scanf("%d",&x);root[edt]=root[x];}if(op==3){scanf("%d%d",&x,&y);if(find_fa(edt,x).fa==find_fa(edt,y).fa) printf("1");else printf("0");putchar('\n');}}
}

LCT

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+100;
int n,m,v[N];
struct Link_Cut_Tree{int w[N],fa[N],son[N][2];bool r[N];#define ls son[x][0]#define rs son[x][1]bool nroot(int x){return son[fa[x]][0]==x||son[fa[x]][1]==x;}void PushUp(int x){w[x]=w[ls]^w[rs]^v[x];return;}void PushR(int x){swap(ls,rs);r[x]^=1;return;}void PushDown(int x){if(r[x]){if(ls) PushR(ls);if(rs) PushR(rs);r[x]=0;}return;}void Rotate(int x){int y=fa[x],z=fa[y],k=(son[y][1]==x),w=son[x][!k];if(nroot(y)) son[z][son[z][1]==y]=x;son[x][!k]=y;son[y][k]=w;if(w) fa[w]=y;fa[y]=x;fa[x]=z;PushUp(y);return;}void PushHall(int x){if(nroot(x)) PushHall(fa[x]);PushDown(x); return;}void Splay(int x){int y=x,z=0;PushHall(x);while(nroot(x)){y=fa[x];z=fa[y];if(nroot(y))Rotate((son[y][0]==x)^(son[z][0]==y)?x:y);Rotate(x);} PushUp(x);return;}void Access(int x){for(int y=0;x;x=fa[y=x])Splay(x),rs=y,PushUp(x);return;}void MakeRoot(int x){Access(x);Splay(x);PushR(x);return;}int FindRoot(int x){Access(x);Splay(x);while(ls) PushDown(x),x=ls;Splay(x);return x;}void Split(int x,int y){MakeRoot(x);Access(y);Splay(y);return;}void Link(int x,int y){MakeRoot(x);if(FindRoot(y)!=x) fa[x]=y;}void Cut(int x,int y){MakeRoot(x);if(FindRoot(y)==x&&fa[y]==x&&!son[y][0]){fa[y]=son[x][1]=0;PushUp(x);} }#undef ls#undef rs
}LCT;
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&v[i]);while(m--){int op,x,y;scanf("%d%d%d",&op,&x,&y);if(op==0){LCT.Split(x,y);printf("%d\n",LCT.w[y]);}if(op==1){LCT.Link(x,y);}if(op==2){LCT.Cut(x,y);}if(op==3){LCT.Splay(x);v[x]=y;}}
} 

左偏树

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,m,val[N];
struct Left_tree{int dis[N],fa[N],t[N][2];int Merge(int x,int y){if(!x||!y) return x+y;if(val[x]>val[y]||(val[x]==val[y]&&x>y))swap(x,y);int &ls=t[x][0],&rs=t[x][1];rs=Merge(rs,y);if(dis[ls]<dis[rs]) swap(ls,rs);fa[rs]=fa[ls]=x;dis[x]=dis[rs]+1;return x;}void Del(int x){int ls=t[x][0],rs=t[x][1];fa[ls]=ls;fa[rs]=rs;val[x]=-1;fa[x]=Merge(ls,rs);}int Get(int x){return (fa[x]==x)?(x):(fa[x]=Get(fa[x]));}
}T;
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&val[i]),T.fa[i]=i;while(m--){int op,x,y;scanf("%d%d",&op,&x);if(op==1){scanf("%d",&y);if(val[x]==-1||val[y]==-1)continue;x=T.Get(x);y=T.Get(y);T.Merge(x,y);}if(op==2){if(val[x]==-1){printf("-1\n");continue;}x=T.Get(x);printf("%d\n",val[x]);T.Del(x);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

下一个计划 : .NET/.NET Core应用性能管理

前言 最近几个月一直在研究开源的APM和监控方案&#xff0c;并对比使用了Zipkin,CAT,Sky-walking,PinPoint(仅对比,未实际部署),Elastic APM,TICK Stack,Prometheus等开源产品&#xff0c;其中不乏功能强大的监控和追踪系统&#xff0c;但它们都对.NET/.NET Core没有支持或支持…

详解proxy_pass、upstream与resolver

转载自 详解proxy_pass、upstream与resolver 应用场景 这里列举几个应用场景&#xff0c;下文会针对这几个场景并结合代码进行分析。 &#xff08;1&#xff09;proxy_pass upstream upstream foo.example.com {server 127.0.0.1:8001;}server {listen 80;server_na…

如何用python将srt文件转化成数组形式

原srt文件 0 00:00:00,150 --> 00:00:11,430 Fighting this pandemic needs political commitment and commitment at the highest level possible and the Presidents commitment.1 00:00:11,431 --> 00:00:16,020 you have what it is in it and the would it have se…

架构演化:云原生时代开启之系列一演化篇

信息技术从出现伊始到渐成主流&#xff0c;其趋势经历了软件、开源和云三个阶段&#xff1a; 软件改变世界。纵观人类社会漫长的发展历程&#xff0c;农耕时代、工业时代与信息时代可谓是三个明显分水岭&#xff0c;每个时代人类涉及的领域范畴均喷井式增长。作为信息时代最重要…

mysql出现unblock with 'mysqladmin flush-hosts'

转载自 mysql出现unblock with mysqladmin flush-hosts 朋友发来消息&#xff0c;说一个系统应用登录的时候提示连接超时&#xff0c;让帮忙处理一下。 问他应用和数据库是否都正常&#xff0c;回复说数据库好像没有问题&#xff0c;但是应用日志报无法连接数据库。 数据库版…

laravel部署到服务器显示Permission denied

解决这个问题可以先cd到项目根目录中 依次输入以下两个命令 find storage -type d -exec chmod 777 {} \;find storage -type f -exec chmod 777 {} \;不报错就证明成功了

亿些模板【数论数学】

文章目录前言数论数学模板GCDexgcd快速幂线性推逆元线性推逆元(非连续)逆元求组合数矩阵乘法线性筛素数-埃氏筛线性筛素数-线性筛线性筛欧拉-埃氏筛线性求欧拉龟速乘FFTNTT分治FFT多项式求逆扩展中国剩余定理Lucas定理高斯消元BSGS拉格朗日插值二次剩余线性基杜教筛前言 因为老…

基于OIDC(OpenID Connect)的SSO

在[认证授权]系列博客中&#xff0c;分别对OAuth2和OIDC在理论概念方面进行了解释说明&#xff0c;其间虽然我有写过一个完整的示例&#xff08;https://github.com/linianhui/oidc.example&#xff09;&#xff0c;但是却没有在实践方面做出过解释。在这里新开一个系列博客&am…

Consul集群搭建

转载自 Consul集群搭建 概述 作为服务发现的几种产品&#xff0c;比较可以查看这里。Consul官方也提供了几种产品之间的比较&#xff0c;点击查看。 服务发现产品 Consul有很多组件&#xff0c;但总体来说&#xff0c;它是一个发现和配置服务工具&#xff0c;特性&#xff…

js遍历对象的key和value

如果想要得到数组的键值对&#xff0c;可以用以下方法 object {"name":"kejin","age":"18"}for(var index in object){console.log(index);console.log(object[index]); }

亿些模板【字符串+其他】

文章目录前言其他快读快输卡常DataMakerDataMakerDataMaker字符串模板KMP字符串hashTrie最小表示法ManacherAC自动机SASAM广义SAMPAM其他模板凸包模拟退火前言 因为老是懒得打模板的时候老是扣不到自己的标(因为之前的都打得太丑了)&#xff0c;所以导致我十分的不爽。便打算开…

使用Identity Server 4建立Authorization Server (6) - js(angular5) 客户端

预备知识: 学习Identity Server 4的预备知识 第一部分: 使用Identity Server 4建立Authorization Server (1) 第二部分: 使用Identity Server 4建立Authorization Server (2) 第三部分: 使用Identity Server 4建立Authorization Server (3) 第四部分: 使用Identity Server 4建立…

SpringBoot整合kafka(实现producer和consumer)

转载自 SpringBoot整合kafka(实现producer和consumer) 在Windows环境下安装运行Kafka&#xff1a;https://www.jianshu.com/p/d64798e81f3b 本文代码使用的是Spring Boot 2.1.1.RELEASE 版本 <parent><groupId>org.springframework.boot</groupId><art…

js的字符串和变量拼接

使用反引号拼接字符串和变量 let count 1 name 用户${count} console.log(name);注意是反引号不是引号&#xff0c;反引号是Esc下面的一个按键

ASP.NET Core 认证与授权[7]:动态授权

基于资源的授权 有些场景下&#xff0c;授权需要依赖于要访问的资源&#xff0c;例如&#xff1a;每个资源通常会有一个创建者属性&#xff0c;我们只允许该资源的创建者才可以对其进行编辑&#xff0c;删除等操作&#xff0c;这就无法通过[Authorize]特性来指定授权了。因为授…

maven中scope属性的

转载自 maven中scope属性的 Dependency Scope 在POM 4中&#xff0c;<dependency>中还引入了<scope>&#xff0c;它主要管理依赖的部署。目前<scope>可以使用5个值&#xff1a; * compile&#xff0c;缺省值&#xff0c;适用于所有阶段&#xff0c;会随着…

P3384-[模板]树链剖分

正题 题目大意 要求支持路径加和求和&#xff0c;子树加和求和 解题思路 树剖不解释 codecodecode #include<cstdio> #include<algorithm> using namespace std; const int N200000; int tot,cnt,n,m,s,p,ls[N],pw[N],id[N]; int siz[N],dep[N],f[N],son[N],seg…

H5的Websocket基本使用

前端代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…

springboot手动提交kafka offset

转载自 springboot手动提交kafka offset enable.auto.commit参数设置成了false 但是测试发现enable.auto.commit参数设置成了false&#xff0c;kafka的offset依然提交了&#xff08;也没有进行人工提交offset&#xff09;。 查看源码 如果我们enable.auto.commit设置为false…

P2114-[NOI2014]起床困难综合症【位运算】

正题 题目大意 若干个位操作&#xff0c;求一个值xxx使得进行了以后的最大值。 解题思路 每位分开运算计算出每一位为0和为1时的结果&#xff0c;然后贪心选择。 codecodecode // luogu-judger-enable-o2 #include<cstdio> using namespace std; int n,m,ans,t; char …