题解-hzy loves segment tree I
Problem
题目概要:给定一棵 \(n\) 个节点的树,点有点权,进行 \(m\) 次路径取\(\max\)的操作,最后统一输出点权
\(n\leq 10^5,m\leq 5\times 10^6\)
Thoughts
今天闲来无事想到的题目,然后就出出来了
我的做法复杂度是\(O(n\log n+m)\),想把\(O(m\log m)\)卡掉,于是一开始把 \(m\) 开到了\(10^7\),后来发现由于常数过大,导致需要跑\(7s\) 虽然其他做法都跑不出来,然后就把数据开小到\(5\times 10^6\),本机\(1.5s\)
后来有人利用stl超高速的\(sort\)过了这题,但需要\(O(m)\)的空间,同样可以卡掉 但凭借着与\(m\)无关的空间复杂度,还是可以将其卡掉
Solution
首先这题有个可并堆的\(O(m\log m)\)的做法,并过不去
算了,还是讲我的做法,这是一个预处理\(O(n\log n)\),单次操作\(O(1)\)的做法
首先套路地将路径按照\(lca\)进行拆分,然后将可以利用st表进行区间标记(然后最后再将所有st表里的东西逐层下传)
由于st表是利用两个可重区间将整个区间进行覆盖,需要找到对应的区间端点的位置,在序列上可以直接找下标,但在树上呢……直接找\(k\)祖先!
好了,其实这就是一道st表找lca+长链剖分求\(k\)祖先+st表逆向应用的三合一(其实这些操作之间可以共用许多东西)
Code
#include <bits/stdc++.h>
using namespace std;
inline void read(int&x){
char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
}
inline void cmax(int&A,int B){A=A>B?A:B;}
const int N=100003;
struct Edge{int v,nxt;}a[N+N];
int head[N],n,m,_;
inline void ad(){
int u,v;read(u),read(v);
a[++_].v=v,a[_].nxt=head[u],head[u]=_;
a[++_].v=u,a[_].nxt=head[v],head[v]=_;
}
namespace data{
typedef long long ll;
const int p=1e9+7;
int u0,u1,v0,v1,w0,w1,i;
inline void reset(){read(u0),read(u1),read(v0),read(v1),read(w0),read(w1);i=0;}
inline void get(int&u,int&v,int&w){
++i;if(i==1){u=u1,v=v1,w=w1;return ;}
u=((ll)i*u1+(ll)(i+1)*u0)%n+1;u0=u1,u1=u;
v=((ll)i*v1+(ll)(i+1)*v0)%n+1;v0=v1,v1=v;
w=((ll)i*w1+(ll)(i+1)*w0)%p+1;w0=w1,w1=w;
}
}
int fa[N],son[N];
int dep[N],len[N],top[N];
int dfs_seq[N+N],dfc;
int in[N],out[N];
void main_dfs(int x,int las){
dep[x]=dep[fa[x]=las]+1;
in[x]=++dfc;dfs_seq[dfc]=x;
for(int i=head[x];i;i=a[i].nxt)
if(a[i].v!=las){
main_dfs(a[i].v,x);
dfs_seq[++dfc]=x;
if(len[a[i].v]>len[son[x]])
son[x]=a[i].v;
}
out[x]=dfc;
len[x]=len[son[x]]+1;
}
namespace ST{
int f[20][N],anc[20][N];
void main(){
for(int i=1;i<=n;++i)
anc[0][i]=fa[i];
for(int j=1;j<20;++j)
for(int i=1;i<=n;++i)
anc[j][i]=anc[j-1][anc[j-1][i]];
}
void print(){
for(int j=19;j;--j)
for(int i=1;i<=n;++i){
cmax(f[j-1][i],f[j][i]);
cmax(f[j-1][anc[j-1][i]],f[j][i]);
}
for(int i=1;i<=n;++i)
printf("%d\n",f[0][i]);
}
}
namespace lca{
int st_f[20][N+N],Log[N+N];
inline int get(int x,int y){
int l = min(in[x], in[y]), r = max(out[x], out[y]);
int w = Log[r-l+1];
int t1=st_f[w][l],t2=st_f[w][r-(1<<w)+1];
return dep[t1]<dep[t2]?t1:t2;
}
void main(){
Log[0]=-1;
for(int i=1;i<=dfc;++i)
st_f[0][i]=dfs_seq[i],Log[i]=Log[i>>1]+1;
for(int l=1,len=1;len<=dfc;++l,len<<=1)
for(int i=1;i+len-1<=dfc;++i)
st_f[l][i]=dep[st_f[l-1][i]]<dep[st_f[l-1][i+len]]?st_f[l-1][i]:st_f[l-1][i+len];
return ;
}
}
namespace kth_anc{
const int ks=5;
int up[N*ks],down[N*ks];
int hbit[N];
int tot_up,tot_down;
int down_be[N];
int up_be[N];
inline int get(int x,int k){
if(!k)return x;
int t=hbit[k];
x=ST::anc[t][x];
k-=(1<<t)+dep[x]-dep[top[x]];
x=top[x];
if(!k)return x;
if(k>0)return up[up_be[x]+k];
return down[down_be[x]-k];
}
void dfs(int x,int Top){
top[x]=Top;
if(son[x])dfs(son[x],Top);
for(int i=head[x];i;i=a[i].nxt)
if(a[i].v!=fa[x] and a[i].v!=son[x])
dfs(a[i].v,a[i].v);
}
void main(){
dfs(1,1);
for(int i=1;i<=n;++i)
if(top[i]==i){
int x=i,t=min(len[x],dep[x]);
up_be[i]=tot_up;
while(t--)up[++tot_up]=fa[x],x=fa[x];
x=i,t=len[x];
down_be[i]=tot_down;
while(t--)down[++tot_down]=son[x],x=son[x];
}
for(int i=1;i<=n;++i)hbit[i]=-1;
for(int j=20;~j;--j)
for(int i=1<<j;i<=n;++i)
if(-1==hbit[i])
hbit[i]=j;
}
}
void solve(int o,int x,int w){
int dis=dep[x]-dep[o]+1,t=lca::Log[dis];
cmax(ST::f[t][x],w);
if(dis==(1<<t))return ;
x=kth_anc::get(x,dis-(1<<t));
cmax(ST::f[t][x],w);
}
int main(){
read(n),read(m);
for(int i=1;i<=n;++i)read(ST::f[0][i]);
for(int i=1;i<n;++i)ad();
main_dfs(1,0);
ST::main();
lca::main();
kth_anc::main();
data::reset();
for(int i=1;i<=m;++i){
int x,y,w,o;
data::get(x,y,w);
o=lca::get(x,y);
solve(o,x,w),solve(o,y,w);
}
ST::print();
return 0;
}
题解-hzy loves segment tree I的更多相关文章
- picks loves segment tree I
picks loves segment tree I 题目背景 来源: \(\text {2018 WC Segment Tree Beats}\) 原作者: \(\text {C_SUNSHINE} ...
- 2018.07.29~30 uoj#170. Picks loves segment tree VIII(线段树)
传送门 线段树好题. 维护区间取两种最值,区间加,求区间两种历史最值,区间最小值. 自己的写法调了一个晚上+一个上午+一个下午+一个晚上并没有调出来,90" role="prese ...
- Lintcode247 Segment Tree Query II solution 题解
[题目描述] For an array, we can build a Segment Tree for it, each node stores an extra attribute count t ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- hdu 5086 Revenge of Segment Tree(BestCoder Round #16)
Revenge of Segment Tree Time Limit: 4000/20 ...
- BestCoder#16 A-Revenge of Segment Tree
Revenge of Segment Tree Problem Description In computer science, a segment tree is a tree data struc ...
- [LintCode] Segment Tree Build II 建立线段树之二
The structure of Segment Tree is a binary tree which each node has two attributes startand end denot ...
- [LintCode] Segment Tree Build 建立线段树
The structure of Segment Tree is a binary tree which each node has two attributes start and end deno ...
- Segment Tree Modify
For a Maximum Segment Tree, which each node has an extra value max to store the maximum value in thi ...
随机推荐
- java io系列20之 PipedReader和PipedWriter
本章,我们学习PipedReader和PipedWriter.它们和“PipedInputStream和PipedOutputStream”一样,都可以用于管道通信. PipedWriter 是字符管 ...
- Kafka技术内幕 读书笔记之(三) 消费者:高级API和低级API——消费者消费消息和提交分区偏移量
消费者拉取钱程拉取每个分区的数据,会将分区的消息集包装成一个数据块( FetchedDataChunk )放入分区信息的队列中 . 而每个队列都对应一个消息流( KafkaStream ),消费者客户 ...
- HDU 1025(最长上升子序列)
题意是要在两条平行线间连点,要在线不交叉的前提下尽可能多的连线,问最多能连多少条线. 现假定题中所给的是 9 组点,分别是:1—3,2—8,3—5,4—9,5—2,6—4,7—6,8—7,9—1,如图 ...
- 042、用volume container 共享数据 (2019-03-05 周二)
参考https://www.cnblogs.com/CloudMan6/p/7188479.html volume container 是专门为其他容器提供 volume 的容器,他提供的卷也可以 ...
- flask请求异步执行(转载)
Flask默认是不支持非阻塞IO的,表现为: 当 请求1未完成之前,请求2是需要等待处理状态,效率非常低. 在flask中非阻塞实现可以由2种: 启用flask多线程机制 # Flask from f ...
- python中的顺序表
Python中的list和tuple两种类型采用了顺序表的实现技术,tuple是不可变类型,即不变的顺序表,因此不支持改变其内部状态的任何操作,而其他方面,则与list的性质类似. list的基本实现 ...
- 安装软件出现缺少vcruntime140.dll
安装VC运行库QQ群:616945527 ->VC目录下
- 按科室统计 2.181222版本 关联查询join 不对
SQL: select t0.deptName, t0.deptId, t0.startTime, t0.endTime, IFNULL(t0.num,) as num0, IFNULL(t1.num ...
- 利用openpyxl模块来操作Excel
python 读写 excel 有好多选择,但是,方便操作的库不多,在我尝试了几个库之后,我觉得两个比较方便的库分别是 xlrd/xlwt.openpyxl. 之所以推荐两个库是因为这两个库分别操作的 ...
- Flume配置Multiplexing Channel Selector
1 官网内容 上面配置的是根据不同的heder当中state值走不同的channels,如果是CZ就走c1 如果是US就走c2 c3 其他默认走c4 2 我的详细配置信息 一个监听http端口 然后 ...