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的更多相关文章

  1. picks loves segment tree I

    picks loves segment tree I 题目背景 来源: \(\text {2018 WC Segment Tree Beats}\) 原作者: \(\text {C_SUNSHINE} ...

  2. 2018.07.29~30 uoj#170. Picks loves segment tree VIII(线段树)

    传送门 线段树好题. 维护区间取两种最值,区间加,求区间两种历史最值,区间最小值. 自己的写法调了一个晚上+一个上午+一个下午+一个晚上并没有调出来,90" role="prese ...

  3. 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 ...

  4. 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 ...

  5. hdu 5086 Revenge of Segment Tree(BestCoder Round #16)

    Revenge of Segment Tree                                                          Time Limit: 4000/20 ...

  6. BestCoder#16 A-Revenge of Segment Tree

    Revenge of Segment Tree Problem Description In computer science, a segment tree is a tree data struc ...

  7. [LintCode] Segment Tree Build II 建立线段树之二

    The structure of Segment Tree is a binary tree which each node has two attributes startand end denot ...

  8. [LintCode] Segment Tree Build 建立线段树

    The structure of Segment Tree is a binary tree which each node has two attributes start and end deno ...

  9. Segment Tree Modify

    For a Maximum Segment Tree, which each node has an extra value max to store the maximum value in thi ...

随机推荐

  1. ThinkPHP3.2中字段unique验证出错的解决方法

    protected $_validate=array( array('stu_id','','学号已存在',1,'unique',1), ) 当一次插入多条数据时: 在进行循环 使用create验证时 ...

  2. 7.桥接模式(Bridge Pattern)

    动机(Motivate):    在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化, ...

  3. HTTP深入理解

    HTTP被设计于二十世纪九十年代初期,是一种可扩展的协议, 它是应用层的协议, 通过TCP,或TLS加密的TCP连接来发送, 理论上任何可靠的传输协议都可以使用. 因其良好的扩展性,时至今日,它不仅被 ...

  4. MassTransit 学习

    http://blog.csdn.net/starfd/article/details/50973124

  5. js验证登录注册

    js验证登录注册的优势,在前台直接验证,不需要在后台读取返回数据验证,减轻服务器压力. 登陆验证得必要性,拦截恶意脚本的登录注册攻击.哈哈,当然有些高手是可以直接跳过js验证的. 所以还是后台验证,并 ...

  6. linux xargs【转】

    -i -I 参数区别 http://man.linuxde.net/xargs 它们都是用来作参数扩展替换的,以下两句代码其实效果一样 cat arg.txt|xargs -i sh sk.sh -p ...

  7. Part-Seven

    1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.

  8. TCP简介(一)

    1. TCP如何利用IP达到自己目的 1.1 IP特点 无连接 不可靠 1.2 TCP将应用程序的传输数据分割成合适的数据块 1.3 定时器 1.4 延迟确认 1.5 检验和 1.6 流量控制 2. ...

  9. PHP7 网络编程(四)signal信号【待】

    https://blog.csdn.net/summy_j/article/details/73199069

  10. 外部程序调用Django模块的解决办法

    Question django.core.exceptions.ImproperlyConfigured: Requested setting CACHES, but settings are not ...