BZOJ1036: [ZJOI2008]树的统计Count
来源:互联网 发布:linux 更改机器名称 编辑:程序博客网 时间:2024/06/05 12:00
题目链接
单点修改,区间最大值,区间和。
树链剖分裸的不能再裸了。
LCT也可以完成。
1.树链剖分
#include <cstdio>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#define N 30005 #define M 200005#define INF 1e9#define mod 1000000using namespace std;typedef long long ll;typedef pair<ll,ll> pa;int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f;}int n,m,cnt,ind,T;int b[N<<1],p[N],nextedge[N<<1];int deep[N],fa[N],son[N],sz[N],pos[N],ftree[N],top[N],a[N];class Seg_Tree{ public: int l,r,mx,sum;}e[N<<2];void Add(int x,int y){ cnt++; b[cnt]=y; nextedge[cnt]=p[x]; p[x]=cnt;}void Anode(int x,int y){ Add(x,y);Add(y,x);}void Input_Init(){ n=read(); for(int i=1;i<n;i++) { static int x,y; x=read(),y=read(); Anode(x,y); } for(int i=1;i<=n;i++) a[i]=read();}void Dfs(int x){ sz[x]=1; for(int i=p[x];i;i=nextedge[i]) { int v=b[i]; if(v==fa[x]) continue; deep[v]=deep[x]+1;fa[v]=x; Dfs(v);sz[x]+=sz[v]; son[x]=sz[son[x]]>sz[v]?son[x]:v; }}void dfs(int x,int root){ pos[x]=++ind;ftree[pos[x]]=x; top[x]=root; if(!son[x]) return; dfs(son[x],root); for(int i=p[x];i;i=nextedge[i]) { int v=b[i]; if(v!=fa[x]&&v!=son[x]) dfs(v,v); }}void pushup(int p){ e[p].mx=max(e[p<<1].mx,e[p<<1|1].mx); e[p].sum=e[p<<1].sum+e[p<<1|1].sum;}void Build(int p,int l,int r){ e[p].l=l,e[p].r=r; if(l==r) { e[p].mx=e[p].sum=a[ftree[l]]; return; } int mid=l+r>>1; Build(p<<1,l,mid);Build(p<<1|1,mid+1,r); pushup(p);}void Solve_Change(int p,int x,int y){ int l=e[p].l,r=e[p].r,mid=l+r>>1; if(l==x&&r==x) { e[p].mx=e[p].sum=y; return; } if(x<=mid) Solve_Change(p<<1,x,y); else Solve_Change(p<<1|1,x,y); pushup(p);}int Query_Max(int p,int x,int y){ int l=e[p].l,r=e[p].r,mid=l+r>>1; if(l==x&&y==r) return e[p].mx; if(y<=mid) return Query_Max(p<<1,x,y); if(x>mid) return Query_Max(p<<1|1,x,y); return max(Query_Max(p<<1,x,mid),Query_Max(p<<1|1,mid+1,y));}void Solve_Max(int x,int y){ int fx=top[x],fy=top[y]; int rtn=-INF; while(fx!=fy) { if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy); rtn=max(rtn,Query_Max(1,pos[fx],pos[x])); x=fa[fx],fx=top[x]; } if(deep[x]<deep[y]) swap(x,y); rtn=max(rtn,Query_Max(1,pos[y],pos[x])); printf("%d\n",rtn);}int Query_Sum(int p,int x,int y){ int l=e[p].l,r=e[p].r,mid=l+r>>1; if(l==x&&y==r) return e[p].sum; if(y<=mid) return Query_Sum(p<<1,x,y); if(x>mid) return Query_Sum(p<<1|1,x,y); return Query_Sum(p<<1,x,mid)+Query_Sum(p<<1|1,mid+1,y);}void Solve_Sum(int x,int y){ int fx=top[x],fy=top[y]; int rtn=0; while(fx!=fy) { if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy); rtn+=Query_Sum(1,pos[fx],pos[x]); x=fa[fx],fx=top[x]; } if(deep[x]<deep[y]) swap(x,y); rtn+=Query_Sum(1,pos[y],pos[x]); printf("%d\n",rtn);}void Solve(){ m=read(); char ch[10];static int x,y; while(m--) { scanf("%s",ch);x=read(),y=read(); if(ch[1]=='M') Solve_Max(x,y); else if(ch[1]=='S') Solve_Sum(x,y); else Solve_Change(1,pos[x],y); }}int main(){ Input_Init(); Dfs(1);dfs(1,1);Build(1,1,n); Solve(); return 0;}
刚学LCT。。拿来练习一下。(但是比树链剖分慢很多╮(╯▽╰)╭)
2.LCT
#include <cstdio>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#define N 30005 #define M 2001005#define INF 1e9using namespace std;typedef long long ll;typedef pair<ll,ll> pa;int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f;}int n,m,top,cnt;int b[N<<1],p[N],nextedge[N<<1];int mx[N],tag[N],a[N],son[N][2],st[N],fa[N],sum[N];bool rev[N];void Add(int x,int y){ cnt++; b[cnt]=y; nextedge[cnt]=p[x]; p[x]=cnt;}void Anode(int x,int y){ Add(x,y);Add(y,x);}void dfs(int x){ for(int i=p[x];i;i=nextedge[i]) { int v=b[i]; if(v==fa[x]) continue; fa[v]=x;dfs(v); }}void Input_Init(){ n=read();mx[0]=-INF; for(int i=1;i<n;i++) { static int x,y; x=read(),y=read(); Anode(x,y); } for(int i=1;i<=n;i++) sum[i]=a[i]=mx[i]=read(); dfs(1);}bool isroot(int x){ return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}void pushup(int k){ int l=son[k][0],r=son[k][1]; mx[k]=max(max(mx[l],mx[r]),a[k]); sum[k]=sum[l]+sum[r]+a[k];}void pushdown(int k){ int l=son[k][0],r=son[k][1]; if(rev[k]) { rev[k]=0;rev[l]^=1;rev[r]^=1; swap(son[k][0],son[k][1]); }}void Rotate(int x){ int y=fa[x],z=fa[y],l,r; l=son[y][1]==x;r=l^1; if(!isroot(y)) son[z][son[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[son[x][r]]=y; son[y][l]=son[x][r];son[x][r]=y; pushup(y);pushup(x);}void Splay(int x){ top=0;st[++top]=x; for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; while(top) pushdown(st[top--]); while(!isroot(x)) { int y=fa[x],z=fa[y]; if(!isroot(y)) { if(son[z][0]==y^son[y][0]==x) Rotate(x); else Rotate(y); } Rotate(x); }}void Access(int x){ for(int t=0;x;t=x,x=fa[x]) Splay(x),son[x][1]=t,pushup(x);}void Make_Root(int x){ Access(x);Splay(x);rev[x]^=1;}void Solve_Change(int x,int y){ Splay(x);mx[x]=sum[x]=a[x]=y; pushup(x);}void Solve_Max(int x,int y){ Make_Root(x);Access(y);Splay(y); printf("%d\n",mx[y]);}void Solve_Sum(int x,int y){ Make_Root(x);Access(y);Splay(y); printf("%d\n",sum[y]);}void Solve(){ m=read(); while(m--) { char ch[10];static int x,y; scanf("%s",ch);x=read(),y=read(); if(ch[0]=='C') Solve_Change(x,y); else if(ch[1]=='M') Solve_Max(x,y); else Solve_Sum(x,y); }}int main(){ Input_Init(); Solve(); return 0;}
0 0
- [Bzoj1036][ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- 【BZOJ1036】【ZJOI2008】树的统计Count 树链剖分裸题
- 【ZJOI2008】【BZOJ1036】树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count && LCT
- bzoj1036: [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- 【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
- bzoj1036: [ZJOI2008]树的统计Count
- BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
- bzoj1036: [ZJOI2008]树的统计Count - 树链剖分
- BZOJ1036: [ZJOI2008]树的统计Count
- bzoj1036【ZJOI2008】树的统计Count
- 【树链剖分】[BZOJ1036][ZJOI2008]树的统计Count
- [BZOJ1036] [ZJOI2008]树的统计Count
- [ZJOI2008] [BZOJ1036] 树的统计Count
- 基于Vue的简单的单页面应用
- Lua基础之math库总结(数学函数库)
- 一级考试维护总结
- ubuntu 14.04搭建网站的一些经验
- git 的简单应用
- BZOJ1036: [ZJOI2008]树的统计Count
- Unity动画系统-人形动画的导入
- Vue.js插件开发入门
- AngularJS过滤器
- ionicCSS01_头部、底部和按钮
- 初学者如何使用git上传代码到github
- 整合mybatis时报错:Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespac
- vue入门实战教程 - 用vue高仿饿了吗APP
- mysql 7天一跟踪实现