数链剖分(树的统计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个节点,编号分别 ...
随机推荐
- XML中<beans>属性
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w ...
- C++ Makefile文件编写
对现有的一个C++动态库文件和调用程序,分别编写Makefile文件,从零开始,这里把自己弄明白的一些东西分享给大家. 1.必须明确Linux下,C++的编译器是g++,C语言的是gcc.网上大多数又 ...
- 2D开机动画
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...
- final版本发布评价II
其实我对技术上的问题了解不多,所以有些评语可能说的不对或者压根就没啥用.可直接忽略.请见谅. 1新蜂的俄罗斯方块,UI设计虽然给出了背景和颜色,但是感觉色彩对比也不好,模块之间也不协调.没有更多的说服 ...
- PAT 1017 A除以B
https://pintia.cn/problem-sets/994805260223102976/problems/994805305181847552 本题要求计算A/B,其中A是不超过1000位 ...
- Postgresql迁移数据文件存放位置
1. POSTGRESQL的安装 centos7 里面默认的pgsql的版本是 如果想用更高的版本需要执行以下如下的命令 rpm -ivh https://download.postgresql.or ...
- poj2082 Terrible Sets(单调栈)
Description Let N be the set of all natural numbers {0 , 1 , 2 , . . . }, and R be the set of all re ...
- Strategic Game HDU - 1054(最小顶点覆盖)
最小顶点覆盖:用最少的点,让每条边都至少和其中一个点关联: ...以为自己很聪明..用边连边...最后还是点连点 哎.... hc 写的 匈牙利足够///// #include <iostr ...
- 简易处理图片在div中居中铺满
原文地址:http://www.cnblogs.com/JimmyBright/p/7681089.html 经常需要在一个长宽固定的div里存放一个图片,这个图片长宽未知,所以需要图片自适应div显 ...
- 杭高OI20190125 (genies出题)
/* 当一个人先从自己的内心开始奋斗,他就开始迈向了成功 ——genies (朝阳的二愣子) */ HGOI寒假赛第一场,欢迎来自各种学校的各式各样的巨老233333 感觉自己好渺小.还是NOIP ( ...