bzoj 1036 树的统计Count
题目大意:
一棵树上有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本身
思路:
树链剖分
衣服都不穿的
搞到线段树里,然后维护维护
背一背代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define inf 2139062143
#define ll long long
#define MAXN 30101
#define MOD
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,Cnt,nxt[MAXN*],fst[MAXN],to[MAXN*],val[MAXN];
int fa[MAXN],dep[MAXN],bl[MAXN],cnt[MAXN],hsh[MAXN];
struct data{int mx,sum,l,r;}tr[MAXN*];
void add(int u,int v) {nxt[++Cnt]=fst[u],fst[u]=Cnt,to[Cnt]=v;}
void build(int x)
{
for(int i=fst[x];i;i=nxt[i])
{
if(to[i]==fa[x]) continue;
dep[to[i]]=dep[x]+;
fa[to[i]]=x;
build(to[i]);
cnt[x]+=cnt[to[i]];
}
cnt[x]++;
}
void Build(int x,int chn)
{
int hvs=;hsh[x]=++Cnt,bl[x]=chn;
for(int i=fst[x];i;i=nxt[i])
if(fa[x]!=to[i]&&cnt[hvs]<cnt[to[i]]) hvs=to[i];
if(!hvs) return ;
Build(hvs,chn);
for(int i=fst[x];i;i=nxt[i])
if(fa[x]!=to[i]&&hvs!=to[i]) Build(to[i],to[i]);
}
void s_build(int k,int l,int r)
{
tr[k].l=l,tr[k].r=r;
if(l==r) return ;
int mid=(l+r)>>;
s_build(k<<,l,mid);
s_build(k<<|,mid+,r);
}
void upd(int k,int pos,int x)
{;
int l=tr[k].l,r=tr[k].r;
if(l==r) {tr[k].mx=tr[k].sum=x;return ;}
int mid=(l+r)>>;
if(mid>=pos) upd(k<<,pos,x);
else upd(k<<|,pos,x);
tr[k].mx=max(tr[k<<].mx,tr[k<<|].mx);
tr[k].sum=tr[k<<].sum+tr[k<<|].sum;
}
int q_sum(int k,int a,int b)
{
int l=tr[k].l,r=tr[k].r;
if(l==a&&r==b) return tr[k].sum;
int mid=(l+r)>>;
if(b<=mid) return q_sum(k<<,a,b);
if(a>mid) return q_sum(k<<|,a,b);
else return q_sum(k<<,a,mid)+q_sum(k<<|,mid+,b);
}
int q_mx(int k,int a,int b)
{
int l=tr[k].l,r=tr[k].r;
if(l==a&&r==b) return tr[k].mx;
int mid=(l+r)>>;
if(b<=mid) return q_mx(k<<,a,b);
if(a>mid) return q_mx(k<<|,a,b);
else return max(q_mx(k<<,a,mid),q_mx(k<<|,mid+,b));
}
int main()
{
n=read();int a,b,res;
for(int i=;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);}
for(int i=;i<=n;i++) val[i]=read();fa[]=;
build();Cnt=;
Build(,);
s_build(,,n);
for(int i=;i<=n;i++) upd(,hsh[i],val[i]);
int T=read();
char ch[];
while(T--)
{
scanf("%s",ch);a=read(),b=read();
if(ch[]=='C') {val[a]=b;upd(,hsh[a],b);}
else if(ch[]=='M')
{
res=-inf;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res=max(res,q_mx(,hsh[bl[a]],hsh[a]));
a=fa[bl[a]];
}
res=max(res,q_mx(,min(hsh[a],hsh[b]),max(hsh[a],hsh[b])));
printf("%d\n",res);
}
else if(ch[]=='S')
{
res=;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res+=q_sum(,hsh[bl[a]],hsh[a]);
a=fa[bl[a]];
}
res+=q_sum(,min(hsh[a],hsh[b]),max(hsh[a],hsh[b]));
printf("%d\n",res);
}
}
}
UPD 2018.9.19
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#define ll long long
#define inf 2147383611
#define MAXN 500100
using namespace std;
inline int read()
{
int x=,f=;
char ch;ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,cnt,nxt[MAXN<<],fst[MAXN],to[MAXN<<],val[MAXN];
int fa[MAXN],dep[MAXN],bl[MAXN],sz[MAXN],hsh[MAXN],mx[MAXN<<],sum[MAXN<<];
void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
void dfs(int x)
{
sz[x]=,dep[x]=dep[fa[x]]+;
for(int i=fst[x];i;i=nxt[i])
if(to[i]!=fa[x]) {fa[to[i]]=x;dfs(to[i]);sz[x]+=sz[to[i]];}
}
void Dfs(int x,int anc)
{
hsh[x]=++cnt,bl[x]=anc;int hvs=;
for(int i=fst[x];i;i=nxt[i])
if(dep[to[i]]>dep[x]&&sz[hvs]<sz[to[i]]) hvs=to[i];
if(!hvs) return ;Dfs(hvs,anc);
for(int i=fst[x];i;i=nxt[i])
if(dep[to[i]]>dep[x]&&to[i]!=hvs) {Dfs(to[i],to[i]);}
}
void mdf(int k,int l,int r,int x,int w)
{
if(l==r) {mx[k]=sum[k]=w;return ;}
int mid=(l+r)>>;
if(x<=mid) mdf(k<<,l,mid,x,w);
else mdf(k<<|,mid+,r,x,w);
mx[k]=max(mx[k<<],mx[k<<|]),sum[k]=sum[k<<]+sum[k<<|];
}
int querys(int k,int l,int r,int a,int b)
{
if(l==a&&r==b) return sum[k];
int mid=(l+r)>>;
if(b<=mid) return querys(k<<,l,mid,a,b);
else if(a>mid) return querys(k<<|,mid+,r,a,b);
else return querys(k<<,l,mid,a,mid)+querys(k<<|,mid+,r,mid+,b);
}
int querym(int k,int l,int r,int a,int b)
{
if(l==a&&r==b) return mx[k];
int mid=(l+r)>>;
if(b<=mid) return querym(k<<,l,mid,a,b);
else if(a>mid) return querym(k<<|,mid+,r,a,b);
else return max(querym(k<<,l,mid,a,mid),querym(k<<|,mid+,r,mid+,b));
}
int main()
{
n=read();int a,b,res,T;char ch[];
for(int i=;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);}
dfs();cnt=;Dfs(,);
for(int i=;i<=n;i++) mdf(,,n,hsh[i],read());
T=read();
while(T--)
{
scanf("%s",ch);a=read(),b=read();
if(ch[]=='C') mdf(,,n,hsh[a],b);
else if(ch[]=='M')
{
res=-inf;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res=max(res,querym(,,n,hsh[bl[a]],hsh[a]));
a=fa[bl[a]];
}
res=max(res,querym(,,n,min(hsh[a],hsh[b]),max(hsh[a],hsh[b])));
printf("%d\n",res);
}
else if(ch[]=='S')
{
res=;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res+=querys(,,n,hsh[bl[a]],hsh[a]);
a=fa[bl[a]];
}
res+=querys(,,n,min(hsh[a],hsh[b]),max(hsh[a],hsh[b]));
printf("%d\n",res);
}
}
}
bzoj 1036 树的统计Count的更多相关文章
- BZOJ 1036 树的统计Count 树链剖分模板题
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...
- [置顶] bzoj 1036 树的统计Count 点权值模板
树链剖分 点权型可做模板,链路剖分的思想把点hash到线段树的上,然后可通过n*(log(n)*log(n))的复杂度在树上操作,在线段树上能操作的在链路上都能操作. #include<cstd ...
- BZOJ - 1036 树的统计Count (LCT)
LCT试炼题(代码量居然完爆树剖?) #include<bits/stdc++.h> using namespace std; ,inf=0x3f3f3f3f; ],flp[N],n,m, ...
- BZOJ - 1036 树的统计Count (树链剖分+线段树)
题目链接 #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3f3f3f; ],mx[ ...
- BZOJ 1036 树的统计-树链剖分
[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...
- Codevs 2460 == BZOJ 1036 树的统计
2460 树的统计 2008年省队选拔赛浙江 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 一棵树上有n个节点,编号分别为1 ...
- BZOJ 1036 树的统计
Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...
- HYSBZ 1036 树的统计Count(树链剖分)题解
思路: 树链剖分,不知道说什么...我连模板都不会用 代码: #include<map> #include<ctime> #include<cmath> #incl ...
- BZOJ 1036 树的统计(树链剖分)
点权树链剖分模板题. # include <cstdio> # include <cstring> # include <cstdlib> # include &l ...
随机推荐
- Spring框架系列(二)--装配和注入Bean
企业日常开发中,几乎都是Spring系的框架,无论是SSM.还是现在大火的SpringBoot+JPA/MyBatis,使用最大的目的就是简化开发 基本模块: 核心容器:Beans.Core.Cont ...
- Redis系列(五)--主从复制
单机环境存在的问题: 1.机器故障,直接凉凉 2.容量瓶颈 3.QPS瓶颈 主从复制 对于可拓展平台来说,复制(replication)是必不可少的.replication可以让其他服务器slave拥 ...
- if语句,while语句,do whlie语句,循环语句
总结: 1.定义数组并赋值: var arr=[1,2,3,4]; 2.通过下标访问数组: var str=arr[0]; 3.自定义数组 var arr=new Array(); 4.数组的赋值 a ...
- js一般用法
<1> 通过id查找html元素 var x=document.getElementById("intro"); <2> 通过标签名查找html元素 v ...
- JAVA学习笔记16——线程生命周期
当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New).就绪(Runnable).运行(Running).阻塞(Blocking)和 ...
- valgrind检查代码内存泄漏,5种内存泄漏情况
摘要: valgrind是linux下用于调试程序和查找内存泄露的常用工具.valgrind会报告5种内存泄露,"definitely lost", "indirectl ...
- Maya Calendar POJ - 1008 (模拟)
简述 注意260天的情况,这个地方还是0年 代码 #include <iostream> #include <map> #include <sstream> usi ...
- keep
简介 什么是keepalived呢?keepalived是实现高可用的一种轻量级的技术手段,主要用来防止单点故障(单点故障是指一旦某一点出现故障就会导致整个系统架构的不可用)的发生.之所以说keepa ...
- Django-REST-Framework JWT 实现SSO认证(下)
在上一篇博客中,我已经对JSON Web 认证做了简单的解释,这篇博客是续篇,若不了解,请看上一篇博客:https://www.cnblogs.com/yushenglin/p/10863184.ht ...
- python之cookbook-day03
第一章:数据结构和算法 1.3 保留最后 N 个元素 问题: 在迭代操作或其他操作的时候,怎样只保留最后有限几个元素的历史记录? 解决方案: 保留有限历史记录正是 collections.deque ...