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. Linux 脚本编写基础

    txt去重    http://man.linuxde.net/sort Linux 脚本编写基础 http://www.cnblogs.com/linn/archive/2007/03/05/664 ...

  2. CXF 动态创建客户端调用稳定版本号为2.7.18

    今天用动态创建客户端的方式调用webservice,报了这样一个错: 2017-01-05 20:51:46,029 DEBUG main org.apache.cxf.common.logging. ...

  3. Java里String.split需要注意的用法

    我们常常用String的split()方法去分割字符串,有两个地方值得注意: 1. 当分隔符是句号时("."),需要转义: 由于String.split是基于正则表达式来分割字符串 ...

  4. ZH奶酪:自然语言处理工具LTP语言云调用方法

    前言 LTP语言云平台 不支持离线调用: 支持分词.词性标注.命名实体识别.依存句法分析.语义角色标注: 不支持自定义词表,但是你可以先用其他支持自定义分词的工具(例如中科院的NLPIR)把文本进行分 ...

  5. # 2015-2016-2 《Java程序设计》课程总结

    2015-2016-2 <Java程序设计>课程总结

  6. FineUI(专业版)实现百变通知框(无JavaScript代码)!

    博客园已经越来越不公正了,居然说我这篇文章没有实质的内容!! 我其实真的想问哪些通篇几十个字,没任何代码和技术分享,嚷嚷着送书的文章的就能雄霸博客园首页几天,我这篇文章偏偏就为管理员所容不下. 其实我 ...

  7. Mac 下面 apache 不解析PHP(or PHP 版本不对)的解决办法

    Mac 升级到 EI Caption 之后发现 apache 的配置被重置了,记录下解决的步骤: 在 apache2 配置文件中修改 PHP 的扩展路径即可: vi /etc/apache2/http ...

  8. bzoj4498: 魔法的碰撞

    首先,如果排列确定,那么就可以组合学解决了,不过排列数很多,显然不能枚举. 我们发现如果区间不能重叠的话,总长度减去所有区间长度就是能用的多余格子数. 然而相邻区间可以重叠较小区间一半的长度,因此这些 ...

  9. BZOJ3505 [Cqoi2014]数三角形

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  10. pthread_cond_signal惊群现象

    1.如下代码所示: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include < ...