首页 > 其他分享 >BZOJ1036-[ZJOI2008]树的统计Count&&POJ3237-Tree

BZOJ1036-[ZJOI2008]树的统计Count&&POJ3237-Tree

时间:2022-11-22 21:05:11浏览次数:41  
标签:Count return int sum Tree pos deep edge ZJOI2008


为什么把这两题放在一起呢,因为这两题其实是一道题,只是输入顺序不一样。这里主要以BZOJ1036为例。

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec   Memory Limit: 162 MB

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

​​树链剖分​​裸题。话不多说,上代码。

Code:

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define inf 0x7fffffff
#define N 30005
using namespace std;
int tot=0,deep[N],sz=0,pos[N],on[N],a[N],head[2*N],size[N],fa[N];
struct node
{
int next,vet;
}edge[N*2];
struct tree
{
int l,r,sum,max;
}t[N*4];
void add(int u,int v)
{
edge[++tot].vet=v;
edge[tot].next=head[u];
head[u]=tot;
}
void dfs1(int u)
{
size[u]=1;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].vet;
if(v==fa[u])continue;
fa[v]=u;
deep[v]=deep[u]+1;
dfs1(v);
size[u]+=size[v];
}
}
void dfs2(int u,int top)
{
int k=0;
pos[u]=++sz;
on[u]=top;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].vet;
if(deep[v]>deep[u]&&size[v]>size[k])
k=v;
}
if(k==0)return;
dfs2(k,top);
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].vet;
if(deep[v]>deep[u]&&v!=k)
dfs2(v,v);
}
}
void build(int o,int l,int r)
{
t[o].l=l;t[o].r=r;
if(l==r)return;
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
}
void updata(int o,int p,int val)
{
int l=t[o].l,r=t[o].r;
int mid=(l+r)>>1;
if(l==r)
{
t[o].max=t[o].sum=val;
return;
}
if(p<=mid)updata(o<<1,p,val);else
updata(o<<1|1,p,val);
t[o].sum=t[o<<1].sum+t[o<<1|1].sum;
t[o].max=max(t[o<<1].max,t[o<<1|1].max);
}
int querymax(int o,int x,int y)
{
int l=t[o].l,r=t[o].r;
int mid=(l+r)>>1;
if(l==x&&y==r)return t[o].max;
if(y<=mid)return querymax(o<<1,x,y);else
if(x>mid)return querymax(o<<1|1,x,y);else
return max(querymax(o<<1,x,mid),querymax(o<<1|1,mid+1,y));
}
int querysum(int o,int x,int y)
{
int l=t[o].l,r=t[o].r;
int mid=(l+r)>>1;
if(l==x&&y==r)return t[o].sum;
if(y<=mid)return querysum(o<<1,x,y);else
if(x>mid)return querysum(o<<1|1,x,y);else
return querysum(o<<1,x,mid)+querysum(o<<1|1,mid+1,y);
}
int solvemax(int x,int y)
{
int mx=-inf;
while(on[x]!=on[y])
{
if(deep[on[x]]<deep[on[y]])swap(x,y);
mx=max(mx,querymax(1,pos[on[x]],pos[x]));
x=fa[on[x]];
}
if(pos[x]>pos[y])swap(x,y);
mx=max(mx,querymax(1,pos[x],pos[y]));
return mx;
}
int solvesum(int x,int y)
{
int sum=0;
while(on[x]!=on[y])
{
if(deep[on[x]]<deep[on[y]])swap(x,y);
sum+=querysum(1,pos[on[x]],pos[x]);
x=fa[on[x]];
}
if(pos[x]>pos[y])swap(x,y);
sum+=querysum(1,pos[x],pos[y]);
return sum;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
dfs1(1);
dfs2(1,1);
build(1,1,n);
for(int i=1;i<=n;i++)
updata(1,pos[i],a[i]);
int T;
scanf("%d",&T);
while(T--)
{
char ch[10];
int x,y;
scanf("%s%d%d",ch,&x,&y);
if(ch[0]=='C')
{
a[x]=y;
updata(1,pos[x],y);
}else
if(ch[1]=='M')
printf("%d\n",solvemax(x,y));else
printf("%d\n",solvesum(x,y));
}
return 0;
}

标签:Count,return,int,sum,Tree,pos,deep,edge,ZJOI2008
From: https://blog.51cto.com/u_15888102/5878475

相关文章

  • TreeUtils工具类一行代码实现列表转树【第三版优化】 三级菜单 三级分类 附视频
    一、序言在日常一线开发过程中,总有列表转树的需求,几乎是项目的标配,比方说做多级菜单、多级目录、多级分类等,有没有一种通用且跨项目的解决方式呢?帮助广大技术朋友给业务瘦......
  • 【快应用】account.authorize授权码模式登录报错1102
    ​现象描述在快应用中调用 account.authorize 接口获取AuthorizationCode。应用在其服务端发送请求(必须使用POST方式)到华为OAuth2.0授权服务的“https://oauth-login.c......
  • 【Azure 应用服务】Azure Powershell Function 出错 The term 'Connect-AzAccount' is
    问题描述在AzureFunction中,执行Powershell的Function脚本时,先后出现1:[Error]ERROR:Theterm'Connect-AzAccount'isnotrecognizedasanameofacmdlet,functio......
  • LeetCode199. Binary Tree Right Side View
    题意实现二叉树的右视图方法BFS代码/***Definitionforabinarytreenode.*structTreeNode{*intval;*TreeNode*left;*TreeNode*ri......
  • [ARC152D] Halftree题解
    很好的一道题,即使是我这种菜鸡也感到心潮澎湃。直觉有余,证明不足。思路有余,推导不足。无论是什么比赛,对拍都是最有效的查错方式。本篇题解里的所有图片采用gra......
  • Solution - ARC152D Halftree
    首先\(n\)为偶数时无解,这是显然的,因为一次加两条边,总边数一定是偶数。下面我们证明\(n\)为奇数时一定有解,直接进行构造。首先将每一个点编号加上\(k\)再模\(n\)......
  • Kubernetes_梳理出ServiceAccount服务账号一条线
    前言看图,如下:左下角的Pod需要访问k8s的资源,需要通过中间apiserver的认证、授权、准入控制三个东西,这就需要一个serviceAccount,帮助它完成这个过程,才能访问k8......
  • JAVA多线程——CountDownLatch
    简介:CountDownLatch用给定的计数初始化。await方法阻塞,直到由于countDown()方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的await调用立即返回。......
  • k8s:服务账号service-account相关参数设置:【重点一篇文章】
    为何写这篇文章?!主要在k8s中,serviceaccount是很要要的一个安全特性,官方资料、以及网上资料对这款的相关参数配置又语焉不详。这里也是自己的理解和解释。如有不对,请指......
  • value_counts()
    value_counts()是一种查看表格某列中有多少个不同值的快捷方法,并计算每个不同值有在该列中有多少重复值。importpandasaspdimportnumpyasnpdf1=DataFrame(......