博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷 P4114 Qtree1
阅读量:5076 次
发布时间:2019-06-12

本文共 2470 字,大约阅读时间需要 8 分钟。

Qtree系列都跟树有着莫大的联系,这道题当然也不例外

读完题,我们大概就知道了,这道题非常简单,可以说是模板题。树剖+线段树轻松解决

直接看代码吧

#include
#include
#include
#include
#include
#define ll long long#define gc() getchar()#define maxn 100010using namespace std;inline ll read(){ //很朴素的快读,不多解释 ll a=0;int f=0;char p=gc(); while(!isdigit(p)){f|=p=='-';p=gc();} while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();} return f?-a:a;}void write(ll a){ //很朴素的快写,也不多解释 if(a>9)write(a/10); putchar(a%10+'0');}int n,a[maxn]; //a数组表示点与父亲连边的长度int tot,head[maxn];struct ahaha1{ //前向星存边 int w,to,next;}e[maxn<<1];inline void add(int u,int v,int w){ e[tot].w=w;e[tot].to=v;e[tot].next=head[u];head[u]=tot++;}int f[maxn],sz[maxn],dep[maxn],son[maxn]; //f表示点的父亲,sz表示点的子树上节点个数,dep表示节点的深度,son表示子树最大的子节点void dfs(int u,int fa){ int maxa=0;sz[u]=1; for(int i=head[u];~i;i=e[i].next){ int v=e[i].to;if(v==fa)continue; f[v]=u;dep[v]=dep[u]+1;a[v]=e[i].w; dfs(v,u);sz[u]+=sz[v]; if(sz[v]>maxa)maxa=sz[v],son[u]=v; }}int b[maxn],in[maxn],top[maxn]; //b表示当前编号所指向的点,in表示点的编号,top表示点所在链的顶端void dfs(int u,int fa,int topf){ in[u]=++tot;b[tot]=u;top[u]=topf; if(!son[u])return; dfs(son[u],u,topf); for(int i=head[u];~i;i=e[i].next){ int v=e[i].to;if(v==fa||v==son[u])continue; dfs(v,u,v); }}#define lc p<<1#define rc p<<1|1struct ahaha2{ //线段树太简单不解释 int v;}t[maxn<<2];inline void pushup(int p){ t[p].v=max(t[lc].v,t[rc].v);}void build(int p,int l,int r){ if(l==r){t[p].v=a[b[l]];return;} int m=l+r>>1; build(lc,l,m);build(rc,m+1,r); pushup(p);}void update(int p,int l,int r,int L,int z){ if(l==r){t[p].v=z;return;} int m=l+r>>1; if(m>=L)update(lc,l,m,L,z); else update(rc,m+1,r,L,z); pushup(p);}int query(int p,int l,int r,int L,int R){ if(l>R||r
>1; return max(query(lc,l,m,L,R),query(rc,m+1,r,L,R));}inline void solve_1(){ //从第0条边开始存,每条边存两次,所以输入的第i条边对应的是第2*i-2和第2*i-1条边,谁是儿子改谁 int x=read()*2-2,w=read(),u=e[x].to,v=e[x+1].to; if(f[v]==u)update(1,1,n,in[v],w); else update(1,1,n,in[u],w);}inline void solve_2(){ //链上查询 int x=read(),y=read(),ans=0; while(top[x]!=top[y]){ if(dep[top[x]]
dep[y])swap(x,y); ans=max(ans,query(1,1,n,in[x]+1,in[y])); //但是最后一次存储必须加1否则会多询问一条边 write(ans);putchar('\n');}int main(){memset(head,-1,sizeof head); n=read(); for(int i=1;i

转载于:https://www.cnblogs.com/hanruyun/p/9373059.html

你可能感兴趣的文章
MAC 上升级python为最新版本
查看>>
创业老板不能犯的十种错误
查看>>
Animations介绍及实例
查看>>
判断请求是否为ajax请求
查看>>
【POJ2699】The Maximum Number of Strong Kings(网络流)
查看>>
spring boot配置跨域
查看>>
BZOJ 1996 合唱队(DP)
查看>>
进击吧!阶乘——大数乘法
查看>>
安卓学习资料推荐-25
查看>>
[界面]设定Tab Control控件的颜色
查看>>
linux 下在程序中调用shell命令
查看>>
CCTouchDelegateProtocol
查看>>
tomcat安装出现的闪退问题
查看>>
BZOJ 3105 线性基 高斯消元
查看>>
.NET Unity IOC框架使用实例
查看>>
activex 不能创建对象
查看>>
从壹开始微服务 [ DDD ] 之九 ║从军事故事中,明白领域命令验证(上)
查看>>
Docker基本命令
查看>>
[优先队列][dp] Luogu P5464 缩小社交圈
查看>>
[贪心][优先队列] Jzoj P6275 梦境
查看>>