数链剖分(树的统计Count )
题目链接:https://cn.vjudge.net/contest/279350#problem/C
具体思路:单点更新,区间查询,查询的时候有两种操作,查询区间最大值和区间和。
注意点:在查询的时候,我们应该直接将这个点进行查询,而不是荆这个点在树上的编号进行查询,只有在进入线段树的时候我们才用树上的编号,update的时候也就直接用树上的编号就可以了,注意这个题有点权值会有负值的情况。
AC代码:
#include<iostream>
#include<cstring>
#include<cmath>
#include<stack>
#include<iomanip>
#include<stdio.h>
#include<algorithm>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
# define lson l,m,rt<<
# define rson m+,r,rt<<|
const int maxn = +;
int head[maxn],edgnum,sto[maxn],depth[maxn],Size[maxn],father[maxn];
int son[maxn],ord[maxn],dfsnum,cost[maxn],top[maxn];
int tree1[maxn<<],tree2[maxn<<];
int maxx;
struct node
{
int fr;
int to;
int nex;
} edge[maxn];
void addedge(int fr,int to)
{
edge[edgnum].fr=fr;
edge[edgnum].to=to;
edge[edgnum].nex=head[fr];
head[fr]=edgnum++;
}
void dfs1(int fr,int rt,int dep)
{
depth[fr]=dep;
father[fr]=rt;
son[fr]=-;
Size[fr]=;
for(int i=head[fr]; i!=-; i=edge[i].nex)
{
int to=edge[i].to;
if(to==rt)
continue;
dfs1(to,fr,dep+);
Size[fr]+=Size[to];
if(son[fr]==-||Size[son[fr]]<Size[to])
{
son[fr]=to;
}
}
}
void dfs2(int fr,int rt)
{
ord[fr]=++dfsnum;
top[fr]=rt;
cost[ord[fr]]=sto[fr];
if(son[fr]!=-)
{
dfs2(son[fr],rt);
}
for(int i=head[fr]; i!=-; i=edge[i].nex)
{
int to=edge[i].to;
if(son[fr]!=to&&father[fr]!=to)
{
dfs2(to,to);
}
}
}
void up1(int rt)
{
tree1[rt]=max(tree1[rt<<],tree1[rt<<|]);
}
void up2(int rt)
{
tree2[rt]=tree2[rt<<]+tree2[rt<<|];
}
void buildtree(int l,int r,int rt)
{
if(l==r)
{
tree1[rt]=cost[l];
tree2[rt]=cost[l];
return ;
}
int m=(l+r)>>;
buildtree(lson);
buildtree(rson);
up1(rt);
up2(rt);
}
void query1(int l,int r,int rt,int L,int R)
{
if(L<=l&&R>=r)
{
maxx=max(maxx,tree1[rt]);
return ;
}
int m=(l+r)>>;
if(L<=m)
query1(lson,L,R);
if(R>m)
query1(rson,L,R);
up1(rt);
}
void Query1(int n,int x,int y)
{
maxx=-inf;
int tx=top[x],ty=top[y];
while(tx!=ty)
{
if(depth[tx]<depth[ty])
{
swap(tx,ty);
swap(x,y);
}
query1(,n,,ord[tx],ord[x]);
x=father[tx],tx=top[x];
}
if(depth[x]<depth[y])
{
swap(x,y);
}
query1(,n,,ord[y],ord[x]);
}
int query2(int l,int r,int rt,int L,int R)
{
if(L<=l&&R>=r)
{
return tree2[rt];
}
int ans=;
int m=(l+r)>>;
if(L<=m)
ans+=query2(lson,L,R);
if(R>m)
ans+=query2(rson,L,R);
up2(rt);
return ans;
}
int Query2(int n,int x,int y)
{
int tx=top[x],ty=top[y];
int ans=;
while(tx!=ty)
{
if(depth[tx]<depth[ty])
{
swap(tx,ty);
swap(x,y);
}
ans+=query2(,n,,ord[tx],ord[x]);
x=father[tx],tx=top[x];
}
if(depth[x]<depth[y])
{
swap(x,y);
}
return ans+query2(,n,,ord[y],ord[x]);
}
void update(int l,int r,int rt,int pos,int p)
{
if(l==r)
{
tree1[rt]=p;
tree2[rt]=p;
return ;
}
int m=(l+r)>>;
if(pos<=m)
update(lson,pos,p);
if(pos>m)
update(rson,pos,p);
up1(rt);
up2(rt);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=; i<=n; i++)
{
head[i]=-;
}
int t1,t2;
for(int i=; i<n; i++)
{
scanf("%d %d",&t1,&t2);
addedge(t1,t2);
addedge(t2,t1);
}
for(int i=; i<=n; i++)
{
scanf("%d",&sto[i]);
}
dfs1(,-,);
dfs2(,);
buildtree(,n,);
int q;
char str[];
scanf("%d",&q);
while(q--)
{
scanf("%s",str);
if(str[]=='Q'&&str[]=='M')
{
scanf("%d %d",&t1,&t2);
Query1(n,t1,t2);
printf("%d\n",maxx);
}
else if(str[]=='Q'&&str[]=='S')
{
scanf("%d %d",&t1,&t2);
int ans=Query2(n,t1,t2);
printf("%d\n",ans);
}
else if(str[]=='C')
{
scanf("%d %d",&t1,&t2);
update(,n,,ord[t1],t2);
}
}
return ;
}
数链剖分(树的统计Count )的更多相关文章
- 1036: [ZJOI2008]树的统计Count (树链剖分)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3401 Solved: 1418[Submit] ...
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14982 Solved: 6081[Submit ...
- [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分
树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...
- 【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 ...
- BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )
树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
随机推荐
- mysql学习(1)
开始我们基础的mysql学习 第一部分:补充知识 1. 昨天讲到的mysql初始化密码为空,今天又get到一种新的方法 Mysql安装后需要做的 Mysql安装成功后,默认的root用户密码为空,你可 ...
- Daily Scrum - 12/04
Meeting Minutes 与Qiufeng, Bojie, Zhongqiu, Ran, Travis一起讨论. 确定了最后的UI及Feature. 开始Code Review, 以及有计划的M ...
- 基于Ryu的服务器实现及相关请求访问处理
基于Ryu的服务器实现及相关请求访问处理 前言及问题描述 近期又遇到了一个非常棘手的问题,由于Ryu是通过Python语言开发的,通过Ryu的wsgi的方式建立服务器,无法解析PHP,通过多次方法解决 ...
- ElasticSearch 2 (3) - Breaking Changes
ElasticSearch 2.1.1 (3) - Breaking Changes Search Changes search_type = scan Deprecated GET /my_ind ...
- php四排序-选择排序
原理: 在一列数字中,选出最小数与第一个位置的数交换.然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止.(以下都是升序排列,即从小到大排列) 举例说明: $ ...
- C# 多线程初级汇总
异步委托 创建线程的一种简单方式是定义一个委托,并异步调用它 委托是方法的类型安全的引用 Delegate类还支持异步地调用方法.在后台,Delegate类会创建一个执行任务的线程 投票,并检查委托是 ...
- .net 生成html文件后压缩成zip文件并下载
这里只做一个简单的实例 public ActionResult Index() { string path = Server.MapPath("/test/");//文件输出目录 ...
- Java 8新特性之接口改善(八恶人-1)
Daisy Donergue 多莫歌·黛西 “By woman, you mean her?” 她也能叫女人? Java 8在13年9月发布,写这篇博文的时间已经是17年12月份了.来的有点晚,但是有 ...
- 【字符串算法2】浅谈Manacher算法
[字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述 字符串算法2:Manacher算法 问题:给出字符串S(限制见后)求出最 ...
- 【转】vi 写完文件保存时才发现是 readonly
在MAC上编辑apache配置文件,老是忘记sudo…… readonly的文件保存时提示 add ! to override, 但这仅是对root来说的啊! 百毒了一下竟然还有解决方案!! :w ! ...