BZOJ 1036 树的统计
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
1
2
2
10
6
5
6
5
16
HINT
Source
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- using namespace std;
- #define maxn 30010
- #define root 1
- int n,next[*maxn],side[maxn],toit[*maxn],key[maxn],tot,son[maxn],father[maxn];
- int edge[maxn],pos[maxn],top[maxn],dep[maxn],heavy[maxn],ord[maxn];
- bool in[maxn];
- struct node
- {
- int l,r;
- int best,sum;
- int lc,rc;
- }seg[*maxn];
- inline int big(int a,int b){if (a > b)return a;return b;}
- inline void add(int,int);
- inline void dfs(int,int);
- inline void link(int,int);
- inline void build(int,int);
- inline void change(int,int);
- inline void find_best(int,int);
- inline void find_sum(int,int);
- inline int seg_sum(int,int,int);
- inline int seg_best(int,int,int);
- int main()
- {
- freopen("1036.in","r",stdin);
- freopen("1036.out","w",stdout);
- scanf("%d",&n);
- int i,a,b;
- for (i = ;i<n;i++)
- {
- scanf("%d %d",&a,&b);
- add(a,b); add(b,a);
- }
- for (i = ;i<=n;i++)
- scanf("%d",key+i);
- tot = ;
- dfs(root,);
- tot = ;
- memset(in,,sizeof(in));
- link(root,root);
- tot = ;
- build(,n);
- int T;
- scanf("%d\n",&T);
- char sign[];
- while (T)
- {
- T--;
- scanf("%s %d %d\n",sign,&a,&b);
- if (sign[] == 'Q')
- {
- if (sign[] == 'M')
- find_best(a,b);
- if (sign[] == 'S')
- find_sum(a,b);
- }
- else
- key[a] = b,change(a,);
- }
- return ;
- }
- inline void add(int a,int b)
- {
- tot++;
- toit[tot] = b;
- next[tot] = side[a];
- side[a] = tot;
- }
- inline void dfs(int a,int deep)
- {
- in[a] = true; dep[a] = deep;
- int u = side[a],v;
- son[a] = ;
- while (u != )
- {
- v = toit[u];
- if (!in[v])
- {
- father[v] = a;
- edge[++tot] = v;
- dfs(v,deep+);
- if (son[heavy[a]] < son[v])
- heavy[a] = v;
- son[a] += son[v];
- }
- u = next[u];
- }
- }
- inline void link(int a,int high)
- {
- top[a] = high;
- pos[a] = ++tot;
- ord[tot] = a;
- in[a] = true;
- if (heavy[a] != )
- link(heavy[a],high);
- else return;
- int u = side[a],v;
- while (u != )
- {
- v = toit[u];
- if (!in[v])
- link(v,v);
- u = next[u];
- }
- }
- inline void build(int l,int r)
- {
- seg[tot].l = l;
- seg[tot].r = r;
- if (l == r)
- {
- seg[tot].best = key[ord[l]];
- seg[tot].sum = key[ord[l]];
- return;
- }
- int mid = ((l+r)>>);
- int k = tot;
- seg[k].lc = ++tot;
- build(l,mid);
- seg[k].rc = ++tot;
- build(mid+,r);
- seg[k].best = big(seg[seg[k].lc].best,seg[seg[k].rc].best);
- seg[k].sum = seg[seg[k].lc].sum+seg[seg[k].rc].sum;
- }
- inline void change(int a,int now)
- {
- if (seg[now].l == seg[now].r)
- {
- seg[now].best = key[a];
- seg[now].sum = key[a];
- return;
- }
- if (seg[seg[now].lc].l<=pos[a]&&seg[seg[now].lc].r>=pos[a])
- change(a,seg[now].lc);
- else change(a,seg[now].rc);
- seg[now].best = big(seg[seg[now].lc].best,seg[seg[now].rc].best);
- seg[now].sum = seg[seg[now].lc].sum + seg[seg[now].rc].sum;
- }
- inline void find_sum(int a,int b)
- {
- int sum = ;
- while (top[a] != top[b])
- {
- if (dep[top[a]] >= dep[top[b]])
- {
- sum += seg_sum(pos[top[a]],pos[a],);
- a = father[top[a]];
- }
- else
- {
- sum += seg_sum(pos[top[b]],pos[b],);
- b = father[top[b]];
- }
- }
- if (pos[a] <= pos[b])
- sum += seg_sum(pos[a],pos[b],);
- else
- sum += seg_sum(pos[b],pos[a],);
- printf("%d\n",sum);
- }
- inline void find_best(int a,int b)
- {
- int best = -;
- while (top[a] != top[b])
- {
- if (dep[top[a]] >= dep[top[b]])
- {
- best = big(best,seg_best(pos[top[a]],pos[a],));
- a = father[top[a]];
- }
- else
- {
- best = big(best,seg_best(pos[top[b]],pos[b],));
- b = father[top[b]];
- }
- }
- if (pos[a] <= pos[b])
- best = big(best,seg_best(pos[a],pos[b],));
- else
- best = big(best,seg_best(pos[b],pos[a],));
- printf("%d\n",best);
- }
- inline int seg_best(int l,int r,int now)
- {
- if (seg[now].l >=l && seg[now].r <=r)
- return seg[now].best;
- int ret =-;
- int t;
- t = seg[now].lc;
- if (seg[t].l<=l&&seg[t].r>=l)
- ret = big(ret,seg_best(l,r,t));
- else if (seg[t].l>=l&&seg[t].l<=r)
- ret = big(ret,seg_best(l,r,t));
- else if (seg[t].r>=l&&seg[t].r<=r)
- ret = big(ret,seg_best(l,r,t));
- t = seg[now].rc;
- if (seg[t].l<=l&&seg[t].r>=l)
- ret = big(ret,seg_best(l,r,t));
- else if (seg[t].l>=l&&seg[t].l<=r)
- ret = big(ret,seg_best(l,r,t));
- else if (seg[t].r>=l&&seg[t].r<=r)
- ret = big(ret,seg_best(l,r,t));
- return ret;
- }
- inline int seg_sum(int l,int r,int now)
- {
- if (seg[now].l >=l && seg[now].r <=r)
- return seg[now].sum;
- int ret = ;
- int t;
- t = seg[now].lc;
- if (seg[t].l<=l&&seg[t].r>=l)
- ret += seg_sum(l,r,t);
- else if (seg[t].l>=l&&seg[t].l<=r)
- ret += seg_sum(l,r,t);
- else if (seg[t].r>=l&&seg[t].r<=r)
- ret += seg_sum(l,r,t);
- t = seg[now].rc;
- if (seg[t].l<=l&&seg[t].r>=l)
- ret += seg_sum(l,r,t);
- else if (seg[t].l>=l&&seg[t].l<=r)
- ret += seg_sum(l,r,t);
- else if (seg[t].r>=l&&seg[t].r<=r)
- ret += seg_sum(l,r,t);
- return ret;
- }
BZOJ 1036 树的统计的更多相关文章
- BZOJ 1036 树的统计-树链剖分
[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...
- Codevs 2460 == BZOJ 1036 树的统计
2460 树的统计 2008年省队选拔赛浙江 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 一棵树上有n个节点,编号分别为1 ...
- BZOJ 1036 树的统计Count 树链剖分模板题
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...
- [置顶] bzoj 1036 树的统计Count 点权值模板
树链剖分 点权型可做模板,链路剖分的思想把点hash到线段树的上,然后可通过n*(log(n)*log(n))的复杂度在树上操作,在线段树上能操作的在链路上都能操作. #include<cstd ...
- BZOJ 1036 树的统计(树链剖分)
点权树链剖分模板题. # include <cstdio> # include <cstring> # include <cstdlib> # include &l ...
- bzoj 1036 树的统计Count
题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...
- BZOJ - 1036 树的统计Count (LCT)
LCT试炼题(代码量居然完爆树剖?) #include<bits/stdc++.h> using namespace std; ,inf=0x3f3f3f3f; ],flp[N],n,m, ...
- Bzoj 1036 树的统计 分类: ACM TYPE 2014-12-29 18:55 72人阅读 评论(0) 收藏
Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...
- BZOJ 1036 树的统计 | 树链剖分模板题
又做了一遍--去掉读入优化只有八十行~ #include <cstdio> #include <cstring> #include <algorithm> usin ...
随机推荐
- EnterpriseArchitectect 软件的勾选的几个选项对应的中文意思
Business Process 业务流程 Requirements 需求分析 Use Case 用例 Domain Model 领域模型 Class 类 Database 数据库设计 Compone ...
- Linux下对后台进程通过kill传递信号不起作用的问题
在阅读APUE信号一章时,我遇到Linux下对后台进程通过kill传递信号不起作用的问题 具体情形与如下链接中的老兄一致: http://bbs.csdn.net/topics/390335913?p ...
- 如何将ER图转换成关系模式集
在ER图中,主要是实体类型和联系类型. 1.实体类型的转换 (“——”表示对应关系) 实体类型——关系模式 实体的属性——关系模式的属性 实体标识符——关系模式的键 2.联系的转换 一元联系较简单,三 ...
- Android无法更新sdk的解决办法
修改 windows/system32/drivers/etc/hosts 文件 添加 203.208.46.146 dl.google.com203.208.46.146 dl-ssl.google ...
- 怎样创建TWaver 3D的轮廓选中效果
在一般的游戏中.物体的选中效果会是这样: TWaver 3D中,物体的默认的选中效果一般都是一个方方正正的外框.在HTML5的Mono版本号中,TWaver提供了轮廓线样式的选中效果. 通过例如以下代 ...
- UVA 10627 - Infinite Race(数论)
UVA 10627 - Infinite Race option=com_onlinejudge&Itemid=8&page=show_problem&category=516 ...
- Activity间的跳转,startActivity与startActivityForResult
JreduCh04 2016-07-30跳转 (由一个画面跳转到另一个画面)两种方法:Intent中 startActivity.startActivityForResult.后者可设置request ...
- copssh加bitvise
只是简单记录下自己在成功使用的方案: 目的:为了突破公司对网站和qq的限制 具备的条件:一台云服务器.Copssh_4.1.0.bitvise ssh client 4.62.公司电脑客户端 一.首先 ...
- iOS英文 汉化,如调用相册,相机改“cancel”,“photos”为“取消”,“相机”
调用系统相册.相机发现是英文的系统相簿界面后标题显示“photos”,但是手机语言已经设置显示中文,纠结半天,最终在info.plist设置解决问题. 只需要改三个地方: 1.plist文件中: 2. ...
- HTML页面中启用360浏览器极速模式
今天做页面突然遇到浏览器一直在兼容模式下运行,体验不好,通过查询文档,在<head>中加入<meta name="renderer" content=" ...