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. webstrom live templates

    javascript: 在live templates底部要选择javascript # $('#$END$') $ $($end$) $bd $(document.body) $d $(docume ...

  2. 【转】【MySql】MySql优化要点

    如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求.这个时候NoSQL的出现暂时解决了这一危机 ...

  3. js阿拉伯数字转中文大写

    function DX(n) { if (!/^(0|[1-9]\d*)(\.\d+)?$/.test(n)) return "数据非法"; var unit = "千百 ...

  4. jQuery的一些常用的方法(转载)

    操作元素的样式 主要包括以下几种方式: $("#msg").css("background"); //返回元素的背景颜色 $("#msg") ...

  5. 2015年3月阿里内推(c++研发)实习生电面经历

    2015年3月开学开始就听说阿里会有内推,果不其然在师兄的引荐下推了菜鸟网络,但是在学校的BBS上看到了阿里云部门,而且要会C++,这使我更感兴趣,重新选择了方向,当然最后选择了阿里云.在此分享一下三 ...

  6. sublime编辑器插件

    sublime---插件 http://www.cnblogs.com/dudumao/p/4054086.html sublime--- Emmet插件  使用方法 http://docs.emme ...

  7. python文件读写操作

    操作文件时一般经历以下步骤: 打开文件 操作文件 1.打开文件: 文件句柄 = open('/path/to/file_name','pattern') pattern: r:只读模式,打开文件时默认 ...

  8. spring-初始化完成后运行指定内容

    方案1:继承ApplicationListener public class InstantiationTracingBeanPostProcessor implements ApplicationL ...

  9. Ubuntu 14.04.4官方默认更新源sources.list

    Ubuntu 14.04.4官方默认更新源sources.list # deb cdrom:[Ubuntu LTS _Trusty Tahr_ - Release amd64 (20160217.1) ...

  10. struts2+spring+hibernate(SSH)框架的搭建和总结

    SSH框架:struts2+spring+hibernate,是目前较流行的一种Web应用程序开源集成框架,用于构建灵活.易于扩展的多层Web应用程序. struts2+spring+hibernat ...