bzoj 1036 树链剖分

来源:互联网 发布:桌面图标收纳软件 编辑:程序博客网 时间:2024/06/11 20:31

最近有点小颓废,每天休息也不是很好,实在没状态CF,好久没写题解了,写个水题来除除草

每天被寝室大神各种高端数据结构吓傻不已,前段时间学了下树链剖分,感觉还算比较好写。

size[u]表示以u为根的节点个数,dep[u]表示u的深度,pre[u]表示u的父节点,top[u]表示u所在重链的顶端节点,son[u]表示与在同一重链上的u的儿子节点,id[u]表示u在线段树中的位置,w[id[u]]表示线段树中的点权。

名词解释:   

    重儿子:siz[u]为v的子节点中siz值最大的,那么u就是v的重儿子。
    轻儿子:v的其它子节点。
    重边:点v与其重儿子的连边。
    轻边:点v与其轻儿子的连边。
    重链:由重边连成的路径。
    轻链:轻边

重点性质

    性质1:如果(v,u)为轻边,则siz[u] * 2 < siz[v];

    性质2:从根到某一点的路径上轻链、重链的个数都不大于logn

算法实现:

显然可以dfs求出size,dep,pre,top,son,id,但是大数据可能出现爆栈的情况,于是我们可以用3次循环来求。

第一次正向循环求出pre,dep,再逆向循环求出size,再正向循环求出top,son,id。然后就可以将权值建立到线段树中

建完树就要开始我们核心算法了,比如更新u到v路径,设f1=top[u],f2=top[v],f1!=f2时,若dep[f1]>=dep[f2],更新u到pre[f1]的权值,然后u=pre[f1].当f1=f2时,再更新u到v的权值即可,操作均为logn的。

上代码:

#include<cstdio>#include<algorithm>#include<iostream>#include<climits>#include<cmath>using namespace std;const int N=30005;int n,m,tot,head[N],next[N*2],to[N*2],val[N],pre[N],dep[N],q[N],size[N],son[N],top[N],w[N],id[N];int MAX[N*4],sum[N*4];bool v[N];char s[20];#define lc x << 1#define rc (lc) + 1inline void add(int u,int v){    to[++tot]=v;    next[tot]=head[u];    head[u]=tot;}void update(int x){    MAX[x]=max(MAX[lc],MAX[rc]);    sum[x]=sum[lc]+sum[rc]; }void build(int x,int l,int r){    if(l==r)     {        MAX[x]=sum[x]=w[l];        return ;        }    int mid=(l+r)>>1;    build(lc,l,mid);    build(rc,mid+1,r);    update(x);}void change(int x,int l,int r,int u,int val){    if(l==r)    {        MAX[x]=sum[x]=val;        return ;    }    int mid=(l+r)>>1;    if(u<=mid)  change(lc,l,mid,u,val);    else change(rc,mid+1,r,u,val);    update(x);   }int qmax(int x,int l,int r,int ql,int qr){    if(ql<=l && qr>=r)  return MAX[x];    int mid=(l+r)>>1;    int tmp1=INT_MIN;int tmp2=INT_MIN;    if(ql<=mid) tmp1=qmax(lc,l,mid,ql,qr);    if(qr>mid)  tmp2=qmax(rc,mid+1,r,ql,qr);    return max(tmp1,tmp2);}int qsum(int x,int l,int r,int ql,int qr){    if(ql<=l && qr>=r)  return sum[x];    int mid=(l+r)>>1;    int tmp1=0;int tmp2=0;    if(ql<=mid) tmp1=qsum(lc,l,mid,ql,qr);    if(qr>mid)  tmp2=qsum(rc,mid+1,r,ql,qr);    return tmp1+tmp2;}inline int gmax(int a,int b){    int tmp=INT_MIN;    while(top[a]!=top[b])    {        if(dep[top[a]]<dep[top[b]]) swap(a,b);        tmp=max(tmp,qmax(1,1,n,id[top[a]],id[a]));         a=pre[top[a]];    }    if(id[a]>id[b])   swap(a,b);    tmp=max(tmp,qmax(1,1,n,id[a],id[b]));    return tmp;}inline int gsum(int a,int b){    int tmp=0;    while(top[a]!=top[b])    {        if(dep[top[a]]<dep[top[b]]) swap(a,b);        tmp+=qsum(1,1,n,id[top[a]],id[a]);         a=pre[top[a]];    }    if(id[a]>id[b])   swap(a,b);    tmp+=qsum(1,1,n,id[a],id[b]);    return tmp;}int main(){    scanf("%d",&n);    int a,b;    for(int i=1;i<n;++i)    {        scanf("%d%d",&a,&b);        add(a,b);        add(b,a);    }    for(int i=1;i<=n;++i)   scanf("%d",&val[i]);    v[dep[1]=q[0]=1]=true;    int r=0;tot=0;    for(int l=0;l<=r;++l)     for(int k=head[q[l]];k;k=next[k])     {        if(!v[to[k]])        {            v[to[k]]=true;            dep[q[++r]=to[k]]=dep[q[l]]+1;            pre[q[r]]=q[l];        }     }    for(int i=r;i>=0;--i)    {        size[pre[q[i]]]+=++size[q[i]];        if(size[q[i]]>size[son[pre[q[i]]]])        son[pre[q[i]]]=q[i];    }     for(int i=0;i<=r;++i)    {        if(!top[q[i]])           for(int k=q[i];k;k=son[k])         {            top[k]=q[i];            w[id[k]=++tot]=val[k];         }    }    build(1,1,n);    scanf("%d",&m);    for(int i=1;i<=m;++i)    {        scanf("%s%d%d",s,&a,&b);        if(s[0]=='C')   change(1,1,n,id[a],b);        else if(s[1]=='M')  printf("%d\n",gmax(a,b));        else printf("%d\n",gsum(a,b));    }    return 0;}





     


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝物流把货弄丢了怎么办 刚买的卡没激活怎么办 腾讯王卡40g用完怎么办 手机欠费不知道电话号码怎么办 手机欠费了不用了怎么办 闲鱼恶意差评怎么办 淘宝买家账户体检中心违规怎么办 淘宝卖家账户体检中心违规怎么办 淘宝好评被删除评价怎么办 淘宝没收到货确认收货了怎么办 美团评论被删怎么办 拼多多恶意差评怎么办 淘宝评论被删了怎么办 淘宝买东西错怪店家了怎么办 淘宝骗删除差评怎么办 淘宝买家号虚假交易违规怎么办 淘宝商家一直不发货怎么办 淘宝商家不发货也不退款怎么办 淘宝买家恶意差评怎么办 淘宝评价完了忘截图了怎么办 12306app登录不上怎么办 淘宝换绑支付宝失败怎么办 淘宝和手机不兼容怎么办 换号之后微信怎么办 手机不兼容的应用程序怎么办 微信版本低登录不了怎么办 软件与系统不兼容怎么办 软件与手机系统不兼容怎么办 qq和手机不兼容怎么办 来个软件不兼容怎么办 安卓8.0不兼容app怎么办 两条内存不兼容怎么办 王者荣耀软件不兼容怎么办 冒险岛不兼容win7怎么办 百度网盘手机号换了怎么办 破解版游戏闪退怎么办 安卓手机软件不兼容怎么办 安卓8.0软件闪退怎么办 游戏与手机系统不兼容怎么办 耳机和手机不兼容怎么办 软件和手机不兼容怎么办