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

4
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

4
1
2
2
10
6
5
6
5
16

思路

又是从浙江挂下来的考数据结构的歪风邪气。

  树链剖分。不过我们不以边为元素,而以点为元素。由于一个点有可能被访问两次,所以在判重方面有一些麻烦。

大体的思想是每次把点向上提的时候处理提到的节点,但不处理当前的节点。。

恩。。这份代码应该是写的比较差吧,就当复习树链剖分了。

 #include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#include <vector>
#include <ctime>
#include <functional>
#define pritnf printf
#define scafn scanf
#define sacnf scanf
#define For(i,j,k) for(int i=(j);i<=(k);(i)++)
#define Clear(a) memset(a,0,sizeof(a))
using namespace std;
typedef unsigned int Uint;
const int INF=0x3fffffff;
///==============struct declaration============== ///==============var declaration=================
const int MAXN=;
int n,q,tot=,k,v,L,R;
int siz[MAXN],son[MAXN],fa[MAXN],top[MAXN],val[MAXN],No[MAXN],depth[MAXN];
int sum[MAXN*],maxv[MAXN*];
vector <int> Edge[MAXN];
///==============function declaration============
void dfs1(int x);void dfs2(int x);void Init();
void Set_Seg(int o,int l,int r);
void update(int o,int l,int r);
int Query_Max(int o,int l,int r);
int Query_Sum(int o,int l,int r);
///==============main code=======================
int main()
{
#define FILE__
#ifdef FILE__
freopen("input","r",stdin);
freopen("output","w",stdout);
#endif
scanf("%d",&n);
for(int i=;i<n;i++){
int s,e;scanf("%d%d",&s,&e);
Edge[s].push_back(e);Edge[e].push_back(s);
}
for(int i=;i<=n;i++) scanf("%d",val+i);
depth[]=;top[]=;dfs1();dfs2();
for(int i=;i<=n;i++){
v=val[i],k=No[i];
Set_Seg(,,n);
}
scanf("%d",&q);
while (q--){
char cmd[];scanf("%s",cmd);
if (cmd[]=='M'){///QMAX
int _max=-INF;int u,v;
scanf("%d%d",&u,&v);if (u==v) _max=val[u];
_max=max(_max,val[u]);
_max=max(_max,val[v]);///if the point locates at a top of a Heavy String
while (u!=v){
if (depth[top[u]]<depth[top[v]]) swap(u,v);///Make u is always deeper
if (top[u]==top[v]){///Locate at the same Heavy String
L=No[u],R=No[v];if (L>R) swap(L,R);L++;R--;
if (L<=R)
_max=max(_max,Query_Max(,,n));
break;
}
if (top[u]==u){///Top of a heavy string
u=fa[u];
_max=max(_max,val[u]);
}
else{///middle of a heavy string
L=No[top[u]],R=No[u];if (L>R) swap(L,R);R--;
_max=max(_max,Query_Max(,,n));u=top[u];
}
}
printf("%d\n",_max);
}
else if (cmd[]=='S'){///QSUM
int _sum=;int u,v;
scanf("%d%d",&u,&v);
_sum+=val[u];
if (u!=v) _sum+=val[v];///if the point locates at a top of a Heavy String
while (u!=v){
if (depth[top[u]]<depth[top[v]]) swap(u,v);///Make u is always deeper
if (top[u]==top[v]){///Locate at the same Heavy String
L=No[v],R=No[u];if (L>R) swap(L,R);L++;R--;
if (L<=R)
_sum+=Query_Sum(,,n);
break;
}
if (top[u]==u){///Top of a heavy string
u=fa[u];
if (u!=v)
_sum+=val[u];
}
else{///middle of a heavy string
L=No[top[u]],R=No[u];if (L>R) swap(L,R);R--;
_sum+=Query_Sum(,,n);u=top[u];
}
}
printf("%d\n",_sum);
}
else if (cmd[]=='H'){///Change
scanf("%d%d",&k,&v);val[k]=v;k=No[k];
Set_Seg(,,n);
}
}
return ;
}
///================fuction code====================
void dfs1(int x){
siz[x]=;son[x]=-;
for(int i=;i<Edge[x].size();i++){
int &e=Edge[x][i];
if (fa[x]==e) continue;
fa[e]=x;depth[e]=depth[x]+;dfs1(e);
siz[x]+=siz[e];
if (son[x]==-||siz[son[x]]<siz[e])
son[x]=e;
}
}
void dfs2(int x){
No[x]=++tot;
if (siz[x]!=) {
top[son[x]]=top[x];
dfs2(son[x]);
}
for(int i=;i<Edge[x].size();i++){
int &e=Edge[x][i];
if (son[x]==e||fa[x]==e) continue;
top[e]=e;dfs2(e);
}
}
void Set_Seg(int o,int l,int r){
int m=(l+r)>>,lc=o*,rc=o*+;
if (l==r){
sum[o]=maxv[o]=v;
return;
}
if (m>=k) Set_Seg(lc,l,m);
else Set_Seg(rc,m+,r);
update(o,l,r);
}
void update(int o,int l,int r){
int lc=o*,rc=o*+;
sum[o]=sum[lc]+sum[rc];
maxv[o]=max(maxv[lc],maxv[rc]);
}
int Query_Max(int o,int l,int r){
if (L<=l&&r<=R)
return maxv[o];
int m=(l+r)>>,lc=o*,rc=o*+;
int Left=-INF,Right=-INF;
if (m>=L) Left=Query_Max(lc,l,m);
if (m<R) Right=Query_Max(rc,m+,r);
return max(Left,Right);
}
int Query_Sum(int o,int l,int r){
if (L<=l&&r<=R)
return sum[o];
int m=(l+r)>>,lc=o*,rc=o*+;
int Left=,Right=;
if (m>=L) Left=Query_Sum(lc,l,m);
if (m<R) Right=Query_Sum(rc,m+,r);
return Left+Right;
}

BZOJ 1036

【ZJOI2008】 树的统计 count的更多相关文章

  1. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  2. bzoj1036 [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 12646  Solved: 5085 [Subm ...

  3. BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 14354  Solved: 5802 [Subm ...

  4. 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分

    [BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...

  5. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  6. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 11102  Solved: 4490[Submit ...

  7. 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 12266  Solved: 4945[Submit ...

  8. BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...

  9. 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 7496  Solved: 3078[Submit] ...

  10. bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

    [ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...

随机推荐

  1. Highcharts——让你的网页上图表画的飞起

    Highcharts是一款纯javascript编写的图表库,能够很简单便捷的在Web网站或Web应用中添加交互性的图表,Highcharts目前支持直线图.曲线图.面积图.柱状图.饼图.散点图等多达 ...

  2. OrchardNoCMS vNext如何在VS2015下调试

    由于VS2015还没有出来正式版,ASP.NET 5也是没有出来正式版.所以在你下载了OrchardNoCMS vNext的代码后,需要配置一些东西,才能启动项目,开始调试. 需要注意以下几点: 1. ...

  3. 几个ES6新特性

    ES6是JavaScript语言的下一代标准,已经在2015年6月正式发布了,因为ES6的第一个版本是在2015年发布的,所以又称ECMAScript 2015(简称ES2015).本文主要讲述的是E ...

  4. 【Jquery】$.Deferred 对象

    源:http://www.ruanyifeng.com/      deferred三个状态 “已完成”“未完成”“已失败”     (1) $.Deferred() 生成一个deferred对象.  ...

  5. Linux 下配置php开发环境

    windows下有一键安装的环境很方便,不过现实中常常服务器是linux系统.想要搭建环境怎么搞呢? 边学变发直播博客,不定期更新.

  6. url 中 # ? & 的作用

    1. # 10年9月,twitter改版.一个显著变化,就是URL加入了"#!"符号.比如,改版前的用户主页网址为http://twitter.com/username改版后,就变 ...

  7. [转]在html中控制自动换行

    其实只要在表格控制中添加一句 <td style="word-break:break-all">就搞定了. 其中可能对英文换行可能会分开一个单词问题:解决如下: 语法: ...

  8. js在手机端不能正确显示

    在html页面head中加入<meta name="viewport" content="width=device-width, initial-scale=1.0 ...

  9. host 文件

    艾玛,果然一个破的小问题也能纠结好久!不过终于过去了... 1. 机器上的host文件目录一般是  /etc/hosts 主要可能会涉及一些网站的安全访问,把网站加入hosts也就意味着 加入了白名单 ...

  10. 【BZOJ-3643】Phi的反函数 数论 + 搜索

    3643: Phi的反函数 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 141  Solved: 96[Submit][Status][Discuss ...