1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 15007  Solved: 6092
[Submit][Status][Discuss]

Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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 <iostream>
#include <algorithm> #define maxn 30001 using namespace std; struct TreeNodeType {
int l,r,dis,mid,max_;
};
struct TreeNodeType tree[maxn<<]; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int if_z,n,m,dis[maxn],Enum,f[maxn],deep[maxn];
int size[maxn],tot,flag[maxn],belong[maxn],dis_[maxn];
int head[maxn],cnt; char Cget; inline void read_int(int &now)
{
if_z=,now=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
edge[++Enum].to=from,edge[Enum].next=head[to],head[to]=Enum;
edge[++Enum].to=to,edge[Enum].next=head[from],head[from]=Enum;
} void search(int now,int fa)
{
int pos=tot++;
f[now]=fa,deep[now]=deep[fa]+;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search(edge[i].to,now);
}
size[now]=tot-pos;
} void search_(int now,int chain)
{
flag[now]=++cnt,belong[now]=chain;
dis_[flag[now]]=dis[now];
int pos=;
for(int i=head[now];i;i=edge[i].next)
{
if(flag[edge[i].to]) continue;
if(size[edge[i].to]>size[pos]) pos=edge[i].to;
}
if(pos!=) search_(pos,chain);
else return ;
for(int i=head[now];i;i=edge[i].next)
{
if(flag[edge[i].to]) continue;
search_(edge[i].to,edge[i].to);
}
} int max(int SOME1,int SOME2)
{
if(SOME1>SOME2) return SOME1;
else return SOME2;
} inline void tree_up(int now)
{
tree[now].dis=tree[now<<].dis+tree[now<<|].dis;
tree[now].max_=max(tree[now<<].max_,tree[now<<|].max_);
} void tree_build(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r;
if(l==r)
{
tree[now].dis=dis_[++cnt];
tree[now].max_=dis_[cnt];
return ;
}
tree[now].mid=(l+r)>>;
tree_build(now<<,l,tree[now].mid);
tree_build(now<<|,tree[now].mid+,r);
tree_up(now);
} void tree_change(int now,int to,int x)
{
if(tree[now].l==tree[now].r&&tree[now].l==to)
{
tree[now].dis=x,tree[now].max_=x;
return ;
}
if(to>tree[now].mid) tree_change(now<<|,to,x);
else tree_change(now<<,to,x);
tree_up(now);
} int tree_query_max(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r)
{
return tree[now].max_;
}
if(l>tree[now].mid) return tree_query_max(now<<|,l,r);
else if(r<=tree[now].mid) return tree_query_max(now<<,l,r);
else return max(tree_query_max(now<<,l,tree[now].mid),tree_query_max(now<<|,tree[now].mid+,r));
} int tree_query_dis(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r)
{
return tree[now].dis;
}
if(l>tree[now].mid) return tree_query_dis(now<<|,l,r);
else if(r<=tree[now].mid) return tree_query_dis(now<<,l,r);
else return tree_query_dis(now<<,l,tree[now].mid)+tree_query_dis(now<<|,tree[now].mid+,r);
} inline int solve_dis(int x,int y)
{
int ans=;
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
ans+=tree_query_dis(,flag[belong[x]],flag[x]);
x=f[belong[x]];
}
ans+=tree_query_dis(,min(flag[x],flag[y]),max(flag[x],flag[y]));
return ans;
} inline int solve_max(int x,int y)
{
int ans=-0x7ffffff;
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
ans=max(ans,tree_query_max(,flag[belong[x]],flag[x]));
x=f[belong[x]];
}
ans=max(ans,tree_query_max(,min(flag[x],flag[y]),max(flag[x],flag[y])));
return ans;
} int main()
{
read_int(n);
int from,to;
for(int i=;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
}
for(int i=;i<=n;i++) read_int(dis[i]);
search(,),search_(,),cnt=,tree_build(,,n);
read_int(m);
char ch[];
for(int i=;i<=m;i++)
{
scanf("%s",ch);read_int(from),read_int(to);
if(ch[]=='C')
{
tree_change(,flag[from],to);
}
else
{
if(ch[]=='S') printf("%d\n",solve_dis(from,to));
else printf("%d\n",solve_max(from,to));
}
}
return ;
}

AC日记——[ZJOI2008]树的统计Count bzoj 1036的更多相关文章

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

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

  2. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  3. BZOJ 题目1036: [ZJOI2008]树的统计Count(Link Cut Tree,改动点权求两个最大值和最大值)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 8421  Solved: 3439 [Submi ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Python开发不可不知的虚拟环境

    一.python3.3之后自带的venv模块 1. 创建虚拟环境 python3.6 -m venv project-env 2. 加入虚拟环境目录 cd pronject-env 3. 激活虚拟环境 ...

  2. 字符编码,ASCII、Unicode与UTF-8的理解

    首先我们先要明白的两点是:1.计算机中的信息都是由二进制的0和1储存的:2.我们再计算机屏幕上看到的各种字符都是计算机系统按照一定的规则将二进制数字转换而来的. 一.基本概念. 1.字符集(chars ...

  3. KMP的正确使用法_x新疆网络赛Query on a string

    Query on a string 题意,给定一个大字符串,给定一个小模式串,定义 两种不同的任务模式,分别是查询和更改: 查询对应区间内,有多少个匹配到位的数字: 修改某一位的某一个字母. 于是直觉 ...

  4. itchat 总结(转)

    python实现微信接口(itchat) 安装 sudo pip install itchat 登录 itchat.auto_login() 这种方法将会通过微信扫描二维码登录,但是这种登录的方式确实 ...

  5. ActiveMQ初步学习

    本文主要参考张丰哲大神的简书文章,链接 https://www.jianshu.com/p/ecdc6eab554c JMS,即Java Message Service,通过面向消息中间件(MOM:M ...

  6. Tensorflow实现Mask R-CNN实例分割通用框架,检测,分割和特征点定位一次搞定(多图)

    Mask R-CNN实例分割通用框架,检测,分割和特征点定位一次搞定(多图)   导语:Mask R-CNN是Faster R-CNN的扩展形式,能够有效地检测图像中的目标,同时还能为每个实例生成一个 ...

  7. IOS开发学习笔记007-数据结构

    目录: 1.全局变量和局部变量 2.结构体 3.结构体数组 4.结构体做函数参数 5.结构体指针 6.枚举 7.总结 一.全局变量和局部变量 全局变量和局部变量的区别 1. 全局变量,再函数外定义的变 ...

  8. AngularJs快速上手掌握

    一.前言 对于前端系列,自然少不了AngularJs的介绍了.在前面文章中,我们介绍了如何使用KnockoutJs来打造一个单页面程序,后面一篇文章将介绍如何使用AngularJs的开发一个单页面应用 ...

  9. [Cocos2dx Bug] [win32] Function CCFileUtils::fullPathFromRelativeFile forget consider the path separated by '\\'

    [Cocos2dx 2.2.4] [win32平台Bug] const char* CCFileUtils::fullPathFromRelativeFile(const char *pszFilen ...

  10. HEAD DETACHED push origin失败问题

    先说HEAD HEAD是一个头指针,通常情况下指向不同的分支,每个分支对应一个commit(准确的说,每个分支对应多个commit,但是只有一个顶层的commit,而commit之间是简单的线性关系. ...