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 ...
随机推荐
- django在验证登录页面时遇到的数据查询问题
数据库查询时针对不存在的用户名进行验证 django在查询数据库时,可以使用get和filter两种方法. 两者的区别 当数据库内不存在该数据时,get会返回异常,而filter会返回空. 当数据库内 ...
- TWaver 3D应用于大型数据中心(续)
在2014年11月份,我们当时发了一篇有关TWaver HTML5 3D应用于大型数据中心的文章,该blog比较详细的描述一些常用的功能的实现方法,比如:动态添加机柜,告警,温度,湿度等相关的功能的具 ...
- 25款css动画库
http://www.swiper.com.cn/usage/animate/index.html //swiper https://cssanimation.io/ http://ianlunn ...
- Python学习-if条件语句
Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 单分支条件语句 if 判断条件: 条件成立,执行该代码块.... 注意:与其他编程语言,如Java和C ...
- ubuntu环境搭建DNS服务器
1 安装bind9 apt install bind9 2 修改 named.conf.local,添加要解析的域名及对应的域名配置文件 zone "test.cn"{ type ...
- buf.readUInt16BE()
buf.readUInt16BE(offset[, noAssert]) buf.readUInt16LE(offset[, noAssert]) offset {Number} 0 <= of ...
- 08 Python基础数据结构
目录: 1) 列表 2) 元组 3) 字符串 4) bytes 5) bytearray 6) 字典 7) 集合 8) 冻集合 """1. 列表特性2. 创建3. 增加4 ...
- codeforces 372 Complete the Word(双指针)
codeforces 372 Complete the Word(双指针) 题链 题意:给出一个字符串,其中'?'代表这个字符是可变的,要求一个连续的26位长的串,其中每个字母都只出现一次 #incl ...
- BNUOJ 33895 D-City
D-City Time Limit: 1000ms Memory Limit: 65535KB This problem will be judged on HDU. Original ID: 449 ...
- 控制公司(codevs 2051)
题目描述 Description 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.例如,福特公司拥有马自达公司12%的股票.据说,如果至少满足了以下三个条件之一,公司A就可以 ...