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 ...
随机推荐
- tf idf公式及sklearn中TfidfVectorizer
在文本挖掘预处理之向量化与Hash Trick中我们讲到在文本挖掘的预处理中,向量化之后一般都伴随着TF-IDF的处理,那么什么是TF-IDF,为什么一般我们要加这一步预处理呢?这里就对TF-IDF的 ...
- Jquery 上一步、下一步及提交
111 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <tit ...
- C++ Primer(第4版)-学习笔记-第4部分:面向对象编程与泛型编程
第15章 面向对象编程OOP(Object-oriented programming) 面向对象编程基于三个基本概念:数据抽象.继承和动态绑定. 在 C++ 中,用类进行 ...
- Linux---shell基本指令
1. 显示当前目录 pwd wangzhengchao@ubuntu:~$ cd /home/wangzhengchao/Desktop/ wangzhengchao@ubuntu:~/Desktop ...
- Oracle 常用目录结构(10g)
大多数情况下,了解Oracle常用目录结构,将大大提高数据库管理与维护的工作效率,本文介绍了Oracle 10g 的常用目录. OFA: 下面给出Oracle 最优灵活体系结构OFA(Optimal ...
- selenium下拉滚动条
selenium下拉滚动条 制作人:全心全意 谷歌浏览器下拉滚动条 chrome = webdriver.Chrome() //创建谷歌浏览器对象 url="http://www.baidu ...
- redis+php+mysql处理高并发实例
一.实验环境ubuntu.php.apache或nginx.mysql二.利用Redis锁解决高并发问题,需求现在有一个接口可能会出现并发量比较大的情况,这个接口使用php写的,做的功能是接收 用户的 ...
- JavaScript学习总结(12)——2016 年 7 个顶级 JavaScript 框架
当涉及到Web开发时,JavaScript框架往往是一些开发人员和企业最受欢迎的平台.可能,你有机会尝试过一两个顶级的JavaScript框架,但你仍然有点不确定哪个才是最佳的最值得掌握的,或者哪个值 ...
- HDU 1254 条件过程复杂的寻找最短路
这里一看就是找箱子到终点的最短路 一开始还傻傻的以为人的位置给的很没有意思- -,然后果然错了 没过多久想明白了错误,因为你推箱子并不是你想去哪里推就能去哪推的,首先得考虑人能否过的去,因为可能人被箱 ...
- 写给对<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">迷惑不解的小伙伴
1.X-UA-Compatible X-UA-Compatible是自从IE8新加的一个设置,对于IE8以下的浏览器是不识别的. 通过在meta中设置X-UA-Compatible的值,可以指定网页的 ...