树链剖分
来源:互联网 发布:php视频网站 编辑:程序博客网 时间:2024/06/05 07:04
题
bzoj3924YES
bzoj4034YES
bzoj1576YES
bzoj3626YES神转化
bzoj2325
bzoj3589
bzoj4538
bzoj2908
bzoj3694YES
bzoj1146二分+树链剖分+线段树套平衡树
bzoj3531YES
bzoj1984YES
bzoj2243YES
bzoj4196YES
bzoj1036YES
poj3237YES
//bzoj3531#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=131072;const int inf=21333333;int dep[N],sz[N],top[N],fa[N],pos[N],h[N];int mx[N*100],sum[N*100],root[N*100],ls[N*100],rs[N*100];int n,m,tot,x,y,z,w[N],c[N],tm,size;struct edge{int y,next;}g[N*2];char s[10];void adp(int x,int y){ g[++tot].y=y; g[tot].next=h[x]; h[x]=tot;}void dfs1(int x){ sz[x]=1; for (int i=h[x];i;i=g[i].next) if (g[i].y!=fa[x]){ fa[g[i].y]=x; dep[g[i].y]=dep[x]+1; dfs1(g[i].y); sz[x]+=sz[g[i].y]; }}void dfs2(int x,int t){ top[x]=t;pos[x]=++tm; int son=0; for (int i=h[x];i;i=g[i].next) if (g[i].y!=fa[x] && sz[son]<sz[g[i].y]) son=g[i].y; if (son) dfs2(son,t); for (int i=h[x];i;i=g[i].next) if (g[i].y!=fa[x] && g[i].y!=son) dfs2(g[i].y,g[i].y);}int lca(int x,int y){ while (top[x]!=top[y]){ if (dep[top[x]]>dep[top[y]]) x=fa[top[x]]; else y=fa[top[y]]; } if (dep[x]<dep[y]) return x; return y;}void pushup(int rt){ sum[rt]=sum[ls[rt]]+sum[rs[rt]]; mx[rt]=max(mx[ls[rt]],mx[rs[rt]]);}void change(int &rt,int l,int r,int k,int val){ if (!rt) rt=++size; if (l==r){mx[rt]=sum[rt]=val;return;} int mid=(l+r)>>1; if (k<=mid) change(ls[rt],l,mid,k,val); else change(rs[rt],mid+1,r,k,val); pushup(rt);}int querymax(int rt,int l,int r,int ll,int rr){ if (!rt) return 0; if (l==ll && rr==r) return mx[rt]; int mid=(l+r)>>1;int res=-inf; if (ll<=mid) res=max(res,querymax(ls[rt],l,mid,ll,min(mid,rr))); if (rr> mid) res=max(res,querymax(rs[rt],mid+1,r,max(mid+1,ll),rr)); return res;}int querysum(int rt,int l,int r,int ll,int rr){ if (!rt) return 0; if (l==ll && rr==r) return sum[rt]; int mid=(l+r)>>1;int res=0; if (ll<=mid) res+=querysum(ls[rt],l,mid,ll,min(mid,rr)); if (rr> mid) res+=querysum(rs[rt],mid+1,r,max(mid+1,ll),rr); return res;}int querysum(int cc,int x,int f){ int res=0; while (top[x]!=top[f]){ res+=querysum(root[cc],1,n,pos[top[x]],pos[x]); x=fa[top[x]]; } res+=querysum(root[cc],1,n,pos[f],pos[x]); return res;}int querymax(int cc,int x,int f){ int res=-inf; while (top[x]!=top[f]){ res=max(res,querymax(root[cc],1,n,pos[top[x]],pos[x])); x=fa[top[x]]; } res=max(res,querymax(root[cc],1,n,pos[f],pos[x])); return res;}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d%d",w+i,c+i); for (int i=1;i<n;i++){ scanf("%d%d",&x,&y); adp(x,y);adp(y,x); } dfs1(1);dfs2(1,1); for (int i=1;i<=n;i++) change(root[c[i]],1,n,pos[i],w[i]); while (m--){ scanf("%s",s); if (s[0]=='Q'){ scanf("%d%d",&x,&y); int f=lca(x,y); if (s[1]=='S') printf("%d\n",querysum(c[x],x,f)+querysum(c[x],y,f)-(c[x]==c[f])*w[f]); else printf("%d\n",max(querymax(c[x],x,f),querymax(c[x],y,f))); } else { scanf("%d%d",&x,&z); if (s[1]=='C'){ change(root[c[x]],1,n,pos[x],0); c[x]=z; change(root[c[x]],1,n,pos[x],w[x]); } else change(root[c[x]],1,n,pos[x],z),w[x]=z; } }}
应用
将树上路径转化为序列用线段树维护。
将某棵子树(dfs序)询问转化为序列用线段树维护。
支持单点修改,路径修改,子树修改。
支持路径求和….
注意:树的形态不能变。
0 0
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 论文笔记:Recurrent Models of Visual Attention
- Spark配置参数中英文对照
- java 中 map.get(key) 的类型转换
- AngularJS的学习--$on、$emit和$broadcast的使用
- 懒汉处理dapper字段名与属性名的映射方式
- 树链剖分
- CRichEditCtrl使用CHARFORMAT这个结构设置字体,颜色,字号
- Linux下用GDB调试多线程程序
- gemotion安装apk出现的INSTALL_FAILED_NO_MATCHING_ABIS错误解决方法
- mac 彻底卸载 node
- 一个三年以上老项目加入React Native 模块的过程
- 腾讯云服务器部署JavaWeb项目
- 03.Java 关键字
- 20170303找女朋友之路思考总结