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 ...
随机推荐
- (独孤九剑)---PHP操作MySQL数据库
[一]开启mysql扩展 在PHP操作MySQL数据库之前,要保证开启了MySQL数据库扩展 若未开启,则可以将php.int文件下的php_mysql开启即可,方式为去掉前面的封号; 配置完成后要重 ...
- 03Servlet API
Servlet API Servlet是实现javax.servlet.Servlet接口的对象.大多数Servlet通过从GenericServlet或HttpServlet类进行扩展来实现.Ser ...
- docker时区
docker cp /etc/localtime <id/name>:/etc/localtime
- valgrind检查代码内存泄漏,5种内存泄漏情况
摘要: valgrind是linux下用于调试程序和查找内存泄露的常用工具.valgrind会报告5种内存泄露,"definitely lost", "indirectl ...
- WIndows 系统下的常用命令 和 检测方法
### 一.检测硬盘速度(Windows 自带工具) #### 使用windows 系统自带的工具测试硬盘读写速度 > 在使用下面命令前,需要获得管理员权限,才会在Dos窗口上显示(否则,一闪而 ...
- 记VS2008安装及使用及卸载的艰辛历程!!!(2018/11/6-2018/11/14)
此文为了纪念我对VS2008“孜孜不倦的”无数次的安装及卸载,以及解决使用过程中出现的问题所花费的人力物力和财力!成功之后再作补充.
- CCF201503-2 数字排序 java(100分)
试题编号: 201503-2 试题名称: 数字排序 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出. 输 ...
- LINUX-YUM 软件包升级器 - (Fedora, RedHat及类似系统)
yum install package_name 下载并安装一个rpm包 yum localinstall package_name.rpm 将安装一个rpm包,使用你自己的软件仓库为你解决所有依赖关 ...
- 关于git上传GitHub以及码云(gitee)
如果你是gitee(码云),点击链接跳转 首先,你的有一个GitHub的账号(然后新建项目我就不说了) # Linux的方法 GitHub网站下的,点击settings下的emails,确认自己的邮箱 ...
- ace & web ide & web code editor
ace & web ide & web code editor web ide https://ace.c9.io/ https://github.com/ajaxorg/ace ht ...