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

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 树的统计的更多相关文章

  1. BZOJ 1036 树的统计-树链剖分

    [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...

  2. Codevs 2460 == BZOJ 1036 树的统计

     2460 树的统计 2008年省队选拔赛浙江 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 一棵树上有n个节点,编号分别为1 ...

  3. BZOJ 1036 树的统计Count 树链剖分模板题

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...

  4. [置顶] bzoj 1036 树的统计Count 点权值模板

    树链剖分 点权型可做模板,链路剖分的思想把点hash到线段树的上,然后可通过n*(log(n)*log(n))的复杂度在树上操作,在线段树上能操作的在链路上都能操作. #include<cstd ...

  5. BZOJ 1036 树的统计(树链剖分)

    点权树链剖分模板题. # include <cstdio> # include <cstring> # include <cstdlib> # include &l ...

  6. bzoj 1036 树的统计Count

    题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...

  7. BZOJ - 1036 树的统计Count (LCT)

    LCT试炼题(代码量居然完爆树剖?) #include<bits/stdc++.h> using namespace std; ,inf=0x3f3f3f3f; ],flp[N],n,m, ...

  8. Bzoj 1036 树的统计 分类: ACM TYPE 2014-12-29 18:55 72人阅读 评论(0) 收藏

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

  9. BZOJ 1036 树的统计 | 树链剖分模板题

    又做了一遍--去掉读入优化只有八十行~ #include <cstdio> #include <cstring> #include <algorithm> usin ...

随机推荐

  1. ImageView 缩放

    <ImageView android:id="@+id/imageview" android:layout_width="wrap_content" an ...

  2. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(37)-文章发布系统④-百万级数据和千万级数据简单测试

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(37)-文章发布系统④-百万级数据和千万级数据简单测试 系列目录 我想测试EF在一百万条数据下的显示时间! ...

  3. c++截取屏幕图片并保存(函数代码实现)

    <strong> //获取桌面窗体的CDC CDC *pdeskdc = GetDesktopWindow()->GetDC(); CRect re; //获取窗体的大小 GetDe ...

  4. Python读写文件需要注意的地方 2015-03-31 23:19 69人阅读 评论(0) 收藏

    <span style="font-family: 'Microsoft YaHei'; background-color: rgb(255, 255, 255);"> ...

  5. Linux内核中SPI/I2c子系统剖析

    Linux内核中,SPI和I2C两个子系统的软件架构是一致的,且Linux内核的驱动模型都以bus,driver,device三种抽象对象为基本元素构建起来.下文的分析将主要用这三种抽象对象的创建过程 ...

  6. systemtap [主设备号,次设备好,inode]监控文件

    SystemTap 是监控和跟踪运行中的linux 内核的操作的动态方法,SystemTap 应用:对管理员,SystemTap可用于监控系统性能,找出系统瓶颈,而对于开发者,可以查看他们的程序运行时 ...

  7. System.Data.DbType 与其它DbType的映射关系

    System.Data.DbType 与其它DbType的映射关系 有如下类型的映射对照: System.Data.SqlClient.SqlDbType System.Data.OleDb.OleD ...

  8. iOS开发集成微信支付

    首先需要理清楚流程: 1.用户使用APP客户端,选择商品下单. 2.商户客户端(就是你做的APP)将用户的商品数据传给商户服务器,请求生成支付订单. 3.商户后台调用统一下单API向微信的服务器发送请 ...

  9. Struts2 result type

    Struts2支持的不同类型的返回结果为: type name 说明 dispatcher 缺省类型,用来转向页面,通常处理JSP chain 转向另一个action,用来处理Action链 redi ...

  10. 9.30 noip模拟试题

    时限均为1s,内存 256MB 1.某种密码(password.*) 关于某种密码有如下描述:某种密码的原文A是由N个数字组成,而密文B是一个长度为N的01数串,原文和密文的关联在于一个钥匙码KEY. ...