BZOJ1036: [ZJOI2008]树的统计Count
2017-01-08 23:29
344 查看
题目链接
单点修改,区间最大值,区间和。
树链剖分裸的不能再裸了。
LCT也可以完成。
1.树链剖分
刚学LCT。。拿来练习一下。(但是比树链剖分慢很多╮(╯▽╰)╭)
2.LCT
单点修改,区间最大值,区间和。
树链剖分裸的不能再裸了。
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 1000000 using 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 ,nextedge[N<<1]; int deep ,fa ,son ,sz ,pos ,ftree ,top ,a ; 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 10153 );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 1e9 using 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 ,nextedge[N<<1]; int mx ,tag ,a ,son [2],st ,fa ,sum ; bool rev ; 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; }
相关文章推荐
- git 的简单应用
- ubuntu 14.04搭建网站的一些经验
- Qt 线程基础(Thread Basics的翻译,线程的五种使用情况)
- 【基础】多线程更新窗体UI的若干方法
- [kuangbin带你飞]专题十 匹配问题 二分图多重匹配
- Java的输入输出与文件读写(一)
- Lua基础之math库总结(数学函数库)
- 基于Vue的简单的单页面应用
- Linux TCP_FASTOPEN的作用
- 数据结构C语言版之表达式求值
- 18.opcode
- HTML --- 盒模型
- dddd
- 中介者模式
- Android ListView 源码分析
- java 线程 原子化 要点
- CSDN博客第一名竟然是由一个Python程序刷出来的?
- 利用webpack和vue实现组件化
- ios 利用UIScrollView实现图片缩放
- iOS获取UUID,并使用keychain存储