【BZOJ 1036】【ZJOI 2008】树的统计 树链剖分模板题
sth神犇的模板:
//bzoj1036 题目:一个n个点的树每个点有一个权值,支持修改单点权值,求某两点路径上的点权和或最大点权。
#include <cstdio>
using namespace std;
int pos[30001],f[30001],up[30001],son[30001],size[30001],a[80001],next[80001],last[30001],sum[100001],max[100001];//pos是指某点在线段树中的位置;f是父节点;up是所在链的最上端;son是众儿子中在同一链中的那一个;size是子树的点数;sum是线段树区间和;max是线段树区间最大值
int n,mm,tot,deep[30001],w[30001],q,que,ll,rr,mmax,ssum,which[30001];
char c;//w是单点权值;which是线段树某位置对应的是哪个点,可看做与pos双向映射。
void build(int x,int y)
{
a[++mm]=y;
next[mm]=last[x];
last[x]=mm;
a[++mm]=x;
next[mm]=last[y];
last[y]=mm;
}
void dfs1(int x)
{
int j,mmax=0,num=0;
size[x]=1;
for (j=last[x];j;j=next[j]) if (a[j]!=f[x])
{
f[a[j]]=x;
deep[a[j]]=deep[x]+1;
dfs1(a[j]);
size[x]+=size[a[j]];
if (size[a[j]]>mmax) {mmax=size[a[j]]; num=a[j];}
}
son[x]=num;
}
void dfs2(int x)
{
pos[x]=++tot;
which[tot]=x;
if (!son[x]) return;
up[son[x]]=up[x];
dfs2(son[x]);
int j;
for (j=last[x];j;j=next[j]) if (a[j]!=f[x]&&a[j]!=son[x])
{
up[a[j]]=a[j];
dfs2(a[j]);
}
}
void buildtree(int now,int l,int r)
{
if (l==r)
{
sum[now]=max[now]=w[which[l]];
return;
}
int x=now<<1;
buildtree(x,l,(l+r)>>1);
buildtree(x+1,((l+r)>>1)+1,r);
if (max[x]>max[x+1]) max[now]=max[x]; else max[now]=max[x+1];
sum[now]=sum[x]+sum[x+1];
}
void change(int now,int l,int r)
{
if (l==r)
{
max[now]=sum[now]=rr;
return;
}
int mid=(l+r)>>1,x=now<<1;
if (ll<=mid) change(x,l,mid); else change(x+1,mid+1,r);
if (max[x]>max[x+1]) max[now]=max[x]; else max[now]=max[x+1];
sum[now]=sum[x]+sum[x+1];
}
void getans(int now,int l,int r)
{
if (l>=ll&&r<=rr)
{
if (max[now]>mmax) mmax=max[now];
ssum+=sum[now];
return;
}
int mid=(l+r)>>1;
if (ll<=mid) getans(now<<1,l,mid);
if (rr>mid) getans((now<<1)+1,mid+1,r);
}
int main()
{
freopen("lx.in","r",stdin);
freopen("lx.out","w",stdout);
scanf("%d",&n);
int i,x,y,tmp;
for (i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
build(x,y);
}
deep[1]=1;
dfs1(1);
up[1]=1;
dfs2(1);
for (i=1;i<=n;i++) scanf("%d",&w[i]);
buildtree(1,1,n);
scanf("%d\n",&que);
for (q=1;q<=que;q++)
{
c=getchar();
if (c=='C')
{
for (i=1;i<=5;i++) c=getchar();
scanf("%d%d\n",&x,&y);//将点x的权值改为r
ll=pos[x];
rr=y;
change(1,1,n);
}
else
{
for (i=1;i<=3;i++) c=getchar();
scanf("%d%d\n",&x,&y);
mmax=-99999999;
ssum=0;
while (up[x]!=up[y])
{
if (deep[up[x]]<deep[up[y]]) {tmp=x; x=y; y=tmp;}
ll=pos[up[x]];
rr=pos[x];
getans(1,1,n);
x=f[up[x]];
}
if (deep[x]>deep[y]) {tmp=x; x=y; y=tmp;}
ll=pos[x];
rr=pos[y];
getans(1,1,n);
if (c=='X') printf("%d\n",mmax);else printf("%d\n",ssum);
}
}
return 0;
}
链剖,xyx说是链抛。给xyx神犇跪了O)Z
不说了,(;′⌒`)这是我的链剖模板。为何在codevs上总是RE?我对codevs逐渐产生了隔膜。
#include<cmath>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
using namespace std;
inline const int max(const int &a,const int &b){return a>b?a:b;}
inline const int min(const int &a,const int &b){return a<b?a:b;}
inline void swapp(int &a,int &b){int c=a;a=b;b=c;}
struct node{int nxt,to;}E[80003];
int N,point[30003],sum[100003],ma[100003],cnt=1,son[30003],up[30003],size[30003],deep[30003];
int pos[30003],which[30003],tot=0,a[30003],fa[30003];
inline void insect(int x,int y){E[cnt].nxt=point[x];E[cnt].to=y;point[x]=cnt++;}
inline void dfs1(int x){
int nmax=0,num=0;
size[x]=1;
for(int tmp=point[x];tmp;tmp=E[tmp].nxt)if (E[tmp].to!=fa[x]){
fa[E[tmp].to]=x;
deep[E[tmp].to]=deep[x]+1;
dfs1(E[tmp].to);
size[x]+=size[E[tmp].to];
if (size[E[tmp].to]>nmax){nmax=size[E[tmp].to];num=E[tmp].to;}
}son[x]=num;
}
inline void dfs2(int x){
pos[x]=++tot;which[tot]=x;
if (!son[x]) return;
up[son[x]]=up[x];
dfs2(son[x]);
for(int tmp=point[x];tmp;tmp=E[tmp].nxt)if ((E[tmp].to!=fa[x])&&(E[tmp].to!=son[x])){
up[E[tmp].to]=E[tmp].to;
dfs2(E[tmp].to);
}
}
inline void buildtree(int l,int r,int rt){
if (l==r){sum[rt]=ma[rt]=a[which[l]];return;}
int mid=(l+r)>>1;
buildtree(l,mid,rt<<1);
buildtree(mid+1,r,rt<<1|1);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);
}
inline void change(int ll,int rr,int l,int r,int rt){
if (l==r){sum[rt]=ma[rt]=rr;return;}
int mid=(l+r)>>1;
if (ll<=mid) change(ll,rr,l,mid,rt<<1);
else change(ll,rr,mid+1,r,rt<<1|1);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);
}
inline int getmax(int L,int R,int l,int r,int rt){
if ((L<=l)&&(r<=R)){return ma[rt];}
int mid=(l+r)>>1,s=-1E9;
if (L<=mid) s=getmax(L,R,l,mid,rt<<1);
if (R>mid) s=max(s,getmax(L,R,mid+1,r,rt<<1|1));
return s;
}
inline void query1(int x,int y){
int mmax=-1E9;
while (up[x]!=up[y]){
if (deep[up[x]]<deep[up[y]])swapp(x,y);
mmax=max(mmax,getmax(pos[up[x]],pos[x],1,N,1));
x=fa[up[x]];
}
if (deep[x]>deep[y])swapp(x,y);
mmax=max(mmax,getmax(pos[x],pos[y],1,N,1));
printf("%d\n",mmax);
}
inline int getsum(int L,int R,int l,int r,int rt){
if ((L<=l)&&(r<=R)){return sum[rt];}
int mid=(l+r)>>1,s=0;
if (L<=mid)s+=getsum(L,R,l,mid,rt<<1);
if (R>mid)s+=getsum(L,R,mid+1,r,rt<<1|1);
return s;
}
inline void query2(int x,int y){
int ssum=0;
while (up[x]!=up[y]){
if (deep[up[x]]<deep[up[y]])swapp(x,y);
ssum+=getsum(pos[up[x]],pos[x],1,N,1);
x=fa[up[x]];
}
if (deep[x]>deep[y])swapp(x,y);
ssum+=getsum(pos[x],pos[y],1,N,1);
printf("%d\n",ssum);
}
int main(){
scanf("%d\n",&N);
CC(point,0);CC(deep,0);CC(size,0);CC(sum,0);CC(ma,0);CC(up,0);CC(son,0);CC(fa,0);
for2(i,1,N){
int x,y;scanf("%d%d\n",&x,&y);
insect(x,y);insect(y,x);
}deep[1]=1;
dfs1(1);
up[1]=1;
dfs2(1);
for1(i,1,N) scanf("%d",&a[i]);
buildtree(1,N,1);
int que;scanf("%d\n",&que);
while (que--){
char c=getchar();
if (c=='C'){
for1(i,1,5)c=getchar();
int ll,rr;scanf("%d%d\n",&ll,&rr);
change(pos[ll],rr,1,N,1);
}else{
for1(i,1,3)c=getchar();
int x,y;scanf("%d%d\n",&x,&y);
if (c=='X') query1(x,y);
else query2(x,y);
}
}return 0;
}
这样就可以了呢,第一次用CA爷的电脑,键盘真好使。
【BZOJ 1036】【ZJOI 2008】树的统计 树链剖分模板题的更多相关文章
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- 树的统计Count---树链剖分
NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14982 Solved: 6081[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 23015 Solved: 9336[Submit ...
- BZOJ 1036 树的统计Count 树链剖分模板题
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...
- 洛谷 P3384 树链剖分(模板题)
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- 洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)
题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...
- spoj - Grass Planting(树链剖分模板题)
Grass Planting 题意 给出一棵树,树有边权.每次给出节点 (u, v) ,有两种操作:1. 把 u 到 v 路径上所有边的权值加 1.2. 查询 u 到 v 的权值之和. 分析 如果这些 ...
随机推荐
- 如何用ZBrush雕刻出栩栩如生的头发(二)
之前的ZBrush教程教大家使用SubTool为模型添加了杂乱头发效果的两种雕刻手法,今天将继续介绍其他方法对模型头发雕刻技巧和细节进行讲解.文章内容仅以fisker老师讲述为例,您也可以按照自己的 ...
- ZBrush中如何才能快速完成脸部雕刻(上)
骨骼,是一门基础艺术,几百年来一直为伟大的艺术大师所研究,它曾经,也将一直是创作现实且可信角色的关键,提高骨骼知识更将大大提高雕刻技能. 查看更多内容请直接前往:http://www.zbrushcn ...
- java解惑 读书笔记
表达式之谜 >奇数性 当取余操作返回一个非0的结果.他与左操作数具有相同的正负符号. >找零谜题 在需要精确答案的地方,要避免使用float和double.对于货币运算.要使用int,lo ...
- javascript中的this应用
1. this作为全局变量2. 作为对象方法的调用3. 作为构造函数调用4. apply调用 this是Javascript语言的一个关键字.它代表函数运行时,自动生成的一个内部对象,只能在函数内部使 ...
- UVALive 6264 Conservation --拓扑排序
题意:一个展览有n个步骤,告诉你每一步在那个场馆举行,总共2个场馆,跨越场馆需要1单位时间,先给你一些约束关系,比如步骤a要在b前执行,问最少的转移时间是多少. 解法:根据这些约束关系可以建立有向边, ...
- AC日记—— codevs 1031 质数环(搜索)
题目描述 Description 一个大小为N(N<=17)的质数环是由1到N共N个自然数组成的一个数环,数环上每两个相邻的数字之和为质数.如下图是一个大小为6的质数环.为了方便描述,规定数环上 ...
- java 20 - 8 字节流的文件复制以及汉字在计算机中的存储方式
复制文本文件:把当前目录下的FileIntputStream.java文件里面的内容复制到当前目录的b.txt文件中 分析: 数据源: FileIntputStream.java -- 读取数据 -- ...
- 移动Web 开发中的一些前端知识收集汇总
在开发DeveMobile 与EaseMobile 主题 的时候积累了一些移动Web 开发的前端知识,本着记录总结的目的,特写这篇文章备忘一下. 要说移动Web 开发与传统的PC 端开发,感觉也没什么 ...
- .NET性能调优之一:ANTS Performance Profiler的使用
.NET性能调优系列文章 系列文章索引 .NET性能调优之一:ANTS Performance Profiler的使用 .NET性能调优之二:使用Visual Studio进行代码度量 .NET性能调 ...
- Web API 安全问题
目录 Web API 安全概览 安全隐患 1. 注入(Injection) 2. 无效认证和Session管理方式(Broken Authentication and Session Manageme ...