bzoj1036 [ZJOI2008]树的统计
一棵树上有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”的操作,每行输出一个整数表示要求输出的结果。
树剖模板。
- #include<cstdio>
- #include<algorithm>
- #include<iostream>
- #include<cmath>
- #include<cstring>
- using namespace std;
- const int INF=1e9+,NN=,MM=1e5+;
- int n,m,sz;
- int a[NN],deep[NN],size[NN],fa[NN],pos[NN],bl[NN];
- int cnt,head[NN],next[MM],rea[MM];
- struct Node
- {
- int l,r,mx,sum;
- }tree[MM];
- void add(int u,int v)
- {
- cnt++;
- next[cnt]=head[u];
- head[u]=cnt;
- rea[cnt]=v;
- }
- void dfs_init(int x)
- {
- size[x]=;
- for (int i=head[x];i!=-;i=next[i])
- {
- int v=rea[i];
- if (v==fa[x]) continue;
- deep[v]=deep[x]+;
- fa[v]=x;
- dfs_init(v);
- size[x]+=size[v];
- }
- }
- void dfs_make(int x,int chain)//chain表示重链首的编号
- {
- int k=;//找重链
- sz++;
- pos[x]=sz;//分配编号;
- bl[x]=chain;
- for (int i=head[x];i!=-;i=next[i])
- {
- int v=rea[i];
- if (deep[v]>deep[x]&&size[v]>size[k]) k=v;
- }
- if (k==) return;
- dfs_make(k,chain);
- for (int i=head[x];i!=-;i=next[i])
- {
- int v=rea[i];
- if (deep[v]>deep[x]&&k!=v) dfs_make(v,v);
- }
- }
- void build(int k,int l,int r)
- {
- tree[k].l=l,tree[k].r=r;
- if (l==r) return;
- int mid=(l+r)>>;
- build(k<<,l,mid),build((k<<)+,mid+,r);
- }
- void change(int k,int x,int y)
- {
- int l=tree[k].l,r=tree[k].r,mid=(l+r)>>;
- if (l==r){tree[k].sum=tree[k].mx=y;return;}
- if (x<=mid) change(k<<,x,y);
- else change(k<<|,x,y);
- tree[k].sum=tree[k<<].sum+tree[k<<|].sum;
- tree[k].mx=max(tree[k<<].mx,tree[k<<|].mx);
- }
- int query_sum(int k,int x,int y)
- {
- int l=tree[k].l,r=tree[k].r,mid=(l+r)>>;
- if (l==x&&r==y) return tree[k].sum;
- if (y<=mid) return query_sum(k<<,x,y);
- else if (x>mid) return query_sum(k<<|,x,y);
- else return query_sum(k<<,x,mid)+query_sum(k<<|,mid+,y);
- }
- int query_max(int k,int x,int y)
- {
- int l=tree[k].l,r=tree[k].r,mid=(l+r)>>;
- if (l==x&&y==r) return tree[k].mx;
- if (y<=mid) return query_max(k<<,x,y);
- else if (x>mid) return query_max(k<<|,x,y);
- else return max(query_max(k<<,x,mid),query_max(k<<|,mid+,y));
- }
- int solve_sum(int x,int y)
- {
- int sum=;
- while (bl[x]!=bl[y])//表示标记不同
- {
- if (deep[bl[x]]<deep[bl[y]]) swap(x,y);
- sum+=query_sum(,pos[bl[x]],pos[x]);
- x=fa[bl[x]]; //跳完整条重链。
- }
- if (pos[x]>pos[y]) swap(x,y);
- sum+=query_sum(,pos[x],pos[y]);
- return sum;
- }
- int solve_max(int x,int y)
- {
- int mx=-INF;
- while (bl[x]!=bl[y])
- {
- if (deep[bl[x]]<deep[bl[y]]) swap(x,y);
- mx=max(mx,query_max(,pos[bl[x]],pos[x]));
- x=fa[bl[x]];
- }
- if (pos[x]>pos[y]) swap(x,y);
- mx=max(mx,query_max(,pos[x],pos[y]));
- return mx;
- }
- int main()
- {
- memset(head,-,sizeof(head));
- scanf("%d",&n);
- for (int i=;i<n;i++)
- {
- int x,y;
- scanf("%d%d",&x,&y);
- add(x,y),add(y,x);
- }
- for (int i=;i<=n;i++)
- scanf("%d",&a[i]);
- dfs_init();
- dfs_make(,);
- build(,,n);//建树。
- for (int i=;i<=n;i++)
- change(,pos[i],a[i]);
- scanf("%d",&m);
- char c[];
- for (int i=;i<=m;i++)
- {
- int x,y;
- scanf("%s%d%d",c,&x,&y);
- if (c[]=='C')
- {
- a[x]=y;
- change(,pos[x],y);
- }
- else
- {
- if (c[]=='M') printf("%d\n",solve_max(x,y));
- else printf("%d\n",solve_sum(x,y));
- }
- }
- }
bzoj1036 [ZJOI2008]树的统计的更多相关文章
- [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分
树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...
- bzoj1036 [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 12646 Solved: 5085 [Subm ...
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...
- bzoj千题计划124:bzoj1036: [ZJOI2008]树的统计Count
http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分板子题 #include<cstdio> #include<iost ...
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1036 题意概括 一个树,每个节点有一个权值.3种操作. 1:修改某一个节点的权值. 2:询问某两个 ...
- 【lct】bzoj1036 [ZJOI2008]树的统计Count
题意:给你一棵树,点带权,支持三种操作:单点修改:询问链上和:询问链上max. 这里的Query操作用了与上一题不太一样的做法(上一题用那种做法,因为在边带权的情况下换根太困难啦): 先ChangeR ...
- BZOJ1036[ZJOI2008]树的统计Count 题解
题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.有一些操作:1.把结点u的权值改为t:2.询问从点u到点v的路径上的节点的最大权值 3.询问从点u到点v的路径上的节点的权值和 ...
- bzoj1036 zjoi2008 树的统计 count
填坑= =第一道裸树剖 #include<cstdio> #include<algorithm> #include<cstring> #include<cst ...
- [BZOJ1036] [ZJOI2008] 树的统计Count (LCT)
Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...
随机推荐
- 网上搜索到的 比较好的mysql查询语句练习题
Sutdent表的定义 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 学号 INT(10) 是 否 是 是 是 Name 姓名 VARCHAR(20) 否 否 是 否 否 Sex 性 ...
- java使用字节流和字符流实现文件复制
大家在Java开发中都会遇到文件复制的文件,众所周知,需要通过文件输入输出流实现. 那究竟该怎么做那,话不多说,直接上代码: 一,使用字节流复制文件 public class FileByteCopy ...
- caffe cifar10试跑问题总结
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #454545 } p. ...
- 通过新浪ip地址库获取用户省份
<script src="http://apps.bdimg.com/libs/jquery/1.11.3/jquery.min.js"></script> ...
- chrome开发工具指南(十四)
模拟和测试其他浏览器 您的任务不只局限于确保网站在 Chrome 和 Android 上出色运行.即使 Device Mode 可以模拟 iPhone 等多种其他设备,我们仍鼓励您查看其他浏览器模拟解 ...
- Java double和 float丢失精度问题
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt357 由于对float或double 的使用不当,可能会出现精度丢失的问题. ...
- C++学习日记(一)————类与对象
C++远征之封装篇(上)笔记 所有内容都是听课笔记,愿课堂视频如下: C++远征之封装篇(上)-慕课网http://www.imooc.com/learn/382 类和对象 1 什么是类,什么是对象 ...
- CCNA+NP学习笔记—序章
本人就读于南京捷式泰网络科技有限公司学习CCIE,这几天准备将多年来的纸质版笔记全部写成电子版献给大家以留下自己学习的足迹.本章是基础篇章,内容较少,主要为之后的内容做铺垫.所有笔记的分类顺序为:序章 ...
- java 多线程(0) Java线程
线程 线程是系统调度的基本单元,每当创建一个进程时,会有许多的线程,也叫轻量级进程,在一个进程中拥有多个线程,各自都有自己的计数器,堆和局部变量属性,并且能够分享内存变量. 为什么要使用多线程 1. ...
- 扫雷游戏制作过程(C#描述):第四节、菜单操作
前言 这里给出教程原文地址. 该项目已经放在github上托管. 菜单操作 我们现在的程序单击菜单的时候不会有任何反应,这一节我们主要介绍菜单的相关代码,使得菜单能够正常使用. 现在我们希望在对应级别 ...