【ZJOI2008】 树的统计 count
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
思路
又是从浙江挂下来的考数据结构的歪风邪气。
树链剖分。不过我们不以边为元素,而以点为元素。由于一个点有可能被访问两次,所以在判重方面有一些麻烦。
大体的思想是每次把点向上提的时候处理提到的节点,但不处理当前的节点。。
恩。。这份代码应该是写的比较差吧,就当复习树链剖分了。
#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的更多相关文章
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
- bzoj1036 [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 12646 Solved: 5085 [Subm ...
- BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 14354 Solved: 5802 [Subm ...
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
[BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 10677 Solved: 4313[Submit ...
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 11102 Solved: 4490[Submit ...
- 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12266 Solved: 4945[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )
树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...
- 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 7496 Solved: 3078[Submit] ...
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...
随机推荐
- jquery的add()用法总结
<!DOCTYPE html> <html> <head lang="en"> <meta charset="utf-8&quo ...
- 关于ipa和apk文件的解压
移动互联网中,主要的两个平台是Android和ios,android上文件的安装包是后缀名为apk的文件,ios上文件的安装包是后缀名为ipa的文件,在本文分析一下这两种文件的特点,以及如何用程序去解 ...
- Threejs 物体闪烁
摸索经验告诉我,对物体的材料关闭深度检测有奇效. 即: depthTest: false 有同类问题的童鞋可以试试.
- Lrc2srt精灵,增加自定义输出编码
2015.4.8 对中文支持有点问题,修改了一下,支持自定义输出编码! 修改了建议行末偏移,通常100到200最好了,人的反应时间! http://files.cnblogs.com/files/ro ...
- WPF Popup 控件导致被遮挡内容不刷新的原因
WPF Popup 控件导致被遮挡内容不刷新的原因 周银辉 今天在写一个WPF控件时用到了Popup控件,很郁闷的情况是:当popup关闭时,原来被popup挡住的界面部分不刷新,非要手动刷新一下(比 ...
- 解决ppt中视频不能播放的问题
小伙伴一直在纠结一个问题,有个ppt,在其他人的电脑上可以正常播放其中的视频,但是在某一个电脑上却总是不能播放,一直没找到原因,俺们今早捯饬了一下,貌似找到一丢丢原因和解决办法了. #1,疑似原因 为 ...
- 【CSS】css自定义字体
源:http://www.cnblogs.com/lhb25/archive/2011/02/11/1951035.html 1.@font-face 定义一个字体 2.例子
- Log4j 简单应用
#输出日志的包路径log4j.logger.com=DEBUG,FILE log4j.rootLogger=WARN,stdout #控制台日志 log4j.appender.stdout=org.a ...
- 高性能集群软件Keepalived(1)
1介绍 Keepalived是linux下一个轻量级的高可用解决方案,与HeartBeat,RoseHA实现的功能类似,但是还是有差别.HeartBeat是一个专业的功能完善的高可用软件,它提供了HA ...
- 用VS开发PHP扩展
开发前准备工作: VS(我用的2013) Cygwin(下载地址:http://www.cygwin.com/) 搭载了php运行环境的IIS7.5 (用来测试) php编译后的程序和编译前的源码,我 ...