|BZOJ 1036|树链剖分|线段树|[ZJOI2008]树的统计Count
来源:互联网 发布:电子科技大学网络教育学费 编辑:程序博客网 时间:2024/06/05 07:44
bzoj 1036
树剖+线段树。
第一个树剖题,终于AC
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define fo(i, j, k) for (i=(j);i<=(k);i++)#define fd(i, k, j) for (i=(k);i>=(j);i--)#define rd(a) scanf("%d", &a)#define rd2(a, b) scanf("%d%d", &a, &b)#define rd3(a, b, c) scanf("%d%d%d", &a, &b, &c)#define ms(i, j) memset(i, j, sizeof i)#define FN2 "bzoj1036" using namespace std;const int MAXN = 30000 + 5;int dep[MAXN], son[MAXN], fa[MAXN], siz[MAXN]; //深度,重儿子,父亲,子树大小 int p[MAXN], top[MAXN], pre; //在线段树中的位置,所在重链顶部,线段树当前标号 int n, wi[MAXN];vector<int> G[MAXN];void dfs1(int u, int f)//第一次dfs记录值 { int i; dep[u] = dep[f] + 1, fa[u] = f, siz[u] = 1; fo (i, 0, G[u].size()-1) { int v = G[u][i]; if (v!=f) { dfs1(v, u); siz[u] += siz[v]; if (son[u]==-1||siz[son[u]]<siz[v]) son[u] = v; } }}void dfs2(int u, int chain) {//第二次dfs连重儿子成重链 int i; p[u] = ++pre, top[u] = chain; if (son[u]!=-1) { dfs2(son[u], chain); fo (i, 0, G[u].size()-1) { int v = G[u][i]; if (v!=son[u]&&v!=fa[u]) dfs2(v, v); } }}int maxv[MAXN*4], sumv[MAXN*4];void pushup(int o) { int lc = o*2, rc = o*2+1; maxv[o] = max(maxv[lc], maxv[rc]); sumv[o] = sumv[lc] + sumv[rc];}void update(int o, int l, int r, int p, int v) { int lc = o*2, rc = o*2+1, M = (l+r)/2; if (l==r) { sumv[o] = maxv[o] = v; return ; } if (p<=M) update(lc, l, M, p, v); else if (M<p) update(rc, M+1, r, p, v); pushup(o);}int getMax(int o, int l, int r, int x, int y) { int lc = o*2, rc = o*2+1, M = (l+r)/2, ret = -200000000; if (x<=l&&r<=y) { return maxv[o]; } if (x<=M) ret = max(ret, getMax(lc, l, M, x, y)); if (M<y) ret = max(ret, getMax(rc, M+1, r, x, y)); return ret;}int getSum(int o, int l, int r, int x, int y) { int lc = o*2, rc = o*2+1, M = (l+r)/2, ret = 0; if (x<=l&&r<=y) { return sumv[o]; } if (x<=M) ret += getSum(lc, l, M, x, y); if (M<y) ret += getSum(rc, M+1, r, x, y); return ret;}int findMax(int u, int v){ int f1 = top[u], f2 = top[v]; int ret = -200000000; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(f1, f2), swap(u, v); ret = max(ret, getMax(1, 1, n, p[f1], p[u])); u = fa[f1], f1 = top[u]; } if (dep[u]<dep[v]) swap(u, v); return max(ret, getMax(1, 1, n, p[v], p[u]));}int findSum(int u, int v){ int f1 = top[u], f2 = top[v]; int ret = 0; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(f1, f2), swap(u, v); ret += getSum(1, 1, n, p[f1], p[u]); u = fa[f1], f1 = top[u]; } if (dep[u]<dep[v]) swap(u, v); return ret+getSum(1, 1, n, p[v], p[u]);}void init() { int i; pre = 0; fo (i, 1, n) dep[i] = fa[i] = siz[i] = p[i] = top[i] = 0, son[i] = -1, G[i].clear(); fo (i, 1, n*4) maxv[i] = -200000000, sumv[i] = 0; fo (i, 1, n-1) { int a, b; rd2(a, b); G[a].push_back(b), G[b].push_back(a); }}void solve() { int q, i; dfs1(1, 0); dfs2(1, 1); fo (i, 1, n) rd(wi[i]), update(1, 1, n, p[i], wi[i]); rd(q); fo (i, 1, q) { char ch[10]; scanf("%s", ch); if (ch[0]=='C') { int u, t; rd2(u, t), update(1, 1, n, p[u], t); } else if (ch[1]=='M') { int u, v; rd2(u, v), printf("%d\n", findMax(u, v)); } else if (ch[1]=='S') { int u, v; rd2(u, v), printf("%d\n", findSum(u, v)); } }}int main() { #ifndef ONLINE_JUDGE freopen(FN2".in","r",stdin);freopen(FN2".out","w",stdout); #endif while (rd(n)==1) init(), solve(); return 0;}
阅读全文
0 0
- 【BZOJ】1036 [ZJOI2008]树的统计Count 树链剖分+线段树
- bzoj 1036 [ZJOI2008]树的统计Count 线段树+树链剖分
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- 【BZOJ 1036】[ZJOI2008]树的统计Count 【树链剖分+线段树】
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分+线段树)
- |BZOJ 1036|树链剖分|线段树|[ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count
- 【bzoj】1036: [ZJOI2008]树的统计Count
- [BZOJ]1036: [ZJOI2008]树的统计Count
- Choco求解器的安装
- 动态规划问题
- Java的JOption函数进行用户交互
- #define、const和enum常量
- 计算几何模板
- |BZOJ 1036|树链剖分|线段树|[ZJOI2008]树的统计Count
- LianLianKan
- org.springframework.context.ApplicationContextAware使用理解
- linux线程学习(2)
- [cloudera hadoop]用sqoop将数据从mysql迁移到hbase中出现的错误
- Struts2_第一个struts应用开发
- 码农测试人员,app开发人员修改hosts神器
- The architecture of VLC media framework
- maven 项目jdk版本配置