Prob.5[线段树/LCA/并查集]模板复习回顾 Upd:2020.3.3

1.并查集:(只加上了路径压缩优化)

int fa[N];
int find(int x)
{
if(fa[x]==x)
return x;
else
{
fa[x]=find(fa[x]);
return fa[x];
}
}
void merge(int x,int y)
{
fa[find(x)]=find(y);
}

初始化:for(int i=1;i<=n;i++) fa[i]=i;

2.线段树:

#include<cstdio>
using namespace std;
const int N=100002;
typedef long long ll;
struct node{
int l,r;
ll val,add;
}t[N*4];
ll a[N];
int n,m;
inline void build(int p,int l,int r)
{
t[p].l=l;t[p].r=r;
int mid=l+r>>1;
if(l==r)
{
t[p].val=a[l];
t[p].add=0;
return;
}
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
t[p].add=0;
t[p].val=t[p<<1].val+t[p<<1|1].val;
return;
}
inline void pushdown(int p)
{
if(t[p].add)
{
t[p<<1].val+=(long long)t[p].add*(t[p<<1].r-t[p<<1].l+1);
t[p<<1|1].val+=(long long)t[p].add*(t[p<<1|1].r-t[p<<1|1].l+1);
t[p<<1].add+=t[p].add;
t[p<<1|1].add+=t[p].add;
t[p].add=0;
}
return;
}
inline void modify(int p,int L,int R,int val)
{
if(L<=t[p].l&&t[p].r<=R)
{
t[p].val+=(long long)val*(t[p].r-t[p].l+1);
t[p].add+=val;
return;
}
if(L>t[p].r || R<t[p].l) return;
pushdown(p);
int mid=t[p].l+t[p].r>>1;
if(L<=mid) modify(p<<1,L,R,val);
if(R>mid) modify(p<<1|1,L,R,val);
t[p].val=t[p<<1].val+t[p<<1|1].val;
return;
}
inline long long query(int p,int L,int R)
{
if(L<=t[p].l&&t[p].r<=R)
return t[p].val;
if(L>t[p].r || R<t[p].l)
return 0;
pushdown(p);
int mid=t[p].l+t[p].r>>1;
ll ans=0;
if(L<=mid) ans+=query(p<<1,L,R);
if(R>mid) ans+=query(p<<1|1,L,R);
return ans;
}
int main()
{
int x,y,k;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
int type;
for(int i=1;i<=m;i++)
{
scanf("%d",&type);
if(type==1)
{
scanf("%d%d%d",&x,&y,&k);
modify(1,x,y,k);
}
if(type==2)
{
scanf("%d%d",&x,&y);
printf("%lld\n",query(1,x,y));
}
}
return 0;
}

3.LCA:倍增法

#include<cstdio>
using namespace std;
const int N=500002,logN=20;
int f[N][logN],dep[N],log[N],n,m,root;
struct node{
int from;
int to;
int next;
}e[N<<1];
int head[N],num;
void addedge(int from,int to)
{
e[++num].from=from;
e[num].to=to;
e[num].next=head[from];
head[from]=num;
}
inline void dfs(int u,int ff)
{
dep[u]=dep[ff]+1;
f[u][0]=ff;
for(int i=1;i<=log[dep[u]];i++)
f[u][i]=f[f[u][i-1]][i-1];
int v;
for(int i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(v==ff)
continue;
dfs(v,u);
}
return;
}
inline void swap(int &a,int &b)
{
int c=a;
a=b;
b=c;
return;
}
inline int ask(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y])
x=f[x][log[dep[x]-dep[y]]];
if(x==y)
return x;
for(int i=log[dep[x]];i>=0;i--)
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
return f[x][0];
}
int main()
{
int x,y;
scanf("%d%d%d",&n,&m,&root);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
log[0]=-1;
for(int i=1;i<=n;i++)
log[i]=log[i>>1]+1;
dfs(root,0);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",ask(x,y));
}
return 0;
}

4.LCA:树链剖分:

#include<cstdio>
using namespace std;
const int N=500002;
struct node{
int from;
int to;
int next;
}e[N<<1];
int head[N],num,n,m,root;
int fa[N],top[N],dep[N],son[N],size[N];
void addedge(int from,int to)
{
e[++num].from=from;
e[num].to=to;
e[num].next=head[from];
head[from]=num;
}
void dfs1(int u,int ff)
{
int v;
size[u]=1;
fa[u]=ff;
dep[u]=dep[ff]+1;
for(int i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(v==ff) continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]])
son[u]=v;
}
return;
}
void dfs2(int u,int ff)
{
int v;
if(son[u])
{
top[son[u]]=top[u];
dfs2(son[u],u);
}
for(int i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(!top[v])
{
top[v]=v;
dfs2(v,u);
}
}
return;
}
void swap(int &a,int &b)
{
int c=a;
a=b;
b=c;
return;
}
inline int ask(int x,int y)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy])
{
swap(x,y);
swap(fx,fy);
}
x=fa[fx];
fx=top[x];
}
if(dep[x]>dep[y])
swap(x,y);
return x;
}
int main()
{
int x,y;
scanf("%d%d%d",&n,&m,&root);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs1(root,0);
dfs2(root,0);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",ask(x,y));
}
return 0;
}

猜你喜欢

转载自www.cnblogs.com/little-cute-hjr/p/12403712.html
upd