洛谷P3178 树上操作 [HAOI2015] 树链剖分

正解:树链剖分+线段树

解题报告:

传送门!

树链剖分+线段树算是基操了趴,,,

就无脑码码码,没有任何含金量,不需要动脑子,然后码量其实也不大,就很爽

比树剖的板子还要板子一些hhhhh

放下代码就欧克了QwQ

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
#define gc getchar()
#define ls(x) (x<<1)
#define rs(x) ((x<<1)|1)
#define t(i) edge[i].to
#define w(i) edge[i].wei
#define fy(i) edge[i].fy
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
#define e(i,x) for(ri i=head[x];i;i=edge[i].nxt)

const int N=5000000+10;
int n,q,ed_cnt,head[N],fa[N],top[N],sz[N],sn[N],dfn[N],low[N],rk[N],dfn_cnt,val[N];
struct ed{int to,nxt;}edge[N];
struct node{int dat,tag;}tr[N];

il int read()
{
    rc ch=gc;ri x=0;rb y=1;
    while(ch!='-' && (ch<'0' || ch>'9'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il char rd(){rc ch=gc;while(ch!='C' && ch!='Q')ch=gc;return ch;}
il void ad(ri x,ri y){edge[++ed_cnt]=(ed){x,head[y]};head[y]=ed_cnt;edge[++ed_cnt]=(ed){y,head[x]};head[x]=ed_cnt;}
void dfs1(ri x,ri fat){sz[x]=1;fa[x]=fat;e(i,x)if(t(i)^fat){dfs1(t(i),x),sz[x]+=sz[t(i)];if(sz[t(i)]>sz[sn[x]] || !sz[x])sn[x]=t(i);}}
void dfs2(ri x,ri tp)
{
    top[x]=tp;rk[dfn[x]=low[x]=++dfn_cnt]=x;if(sn[x])dfs2(sn[x],tp);low[x]=max(low[x],low[sn[x]]);
    e(i,x)if(t(i)^fa[x] && t(i)^sn[x])dfs2(t(i),t(i)),low[x]=low[t(i)];
}
il void pushdown(ri x,ri l,ri r)
{
    if(tr[x].tag)
    {
        ri mid=(l+r)>>1;
        tr[ls(x)].tag+=tr[x].tag;tr[ls(x)].dat+=tr[x].tag*(mid-l+1);
        tr[rs(x)].tag+=tr[x].tag;tr[rs(x)].dat+=tr[x].tag*(r-mid);
        tr[x].tag=0;
    }
}
il void pushup(ri x){tr[x].dat=tr[ls(x)].dat+tr[rs(x)].dat;}
void build(ri x,ri l,ri r)
{
    if(l==r){tr[x].dat=val[rk[l]];return;}
    ri mid=(l+r)>>1;
    build(ls(x),l,mid);build(rs(x),mid+1,r);
    pushup(x);
}
void modify(ri x,ri l,ri r,ri to_l,ri to_r,ri dat)
{
    if(to_l<=l && r<=to_r){tr[x].tag+=dat;tr[x].dat+=dat*(r-l+1);return;}
    pushdown(x,l,r);
    ri mid=(l+r)>>1;
    if(mid>=to_l)modify(ls(x),l,mid,to_l,to_r,dat);
    if(mid<to_r)modify(rs(x),mid+1,r,to_l,to_r,dat);
    pushup(x);
}
int query(ri x,ri l,ri r,ri to_l,ri to_r)
{
    if(l>r)return 0;
    if(to_l<=l && r<=to_r)return tr[x].dat;
    pushdown(x,l,r);
    ri mid=(l+r)>>1,ret=0;
    if(mid>=to_l)ret+=query(ls(x),l,mid,to_l,to_r);
    if(mid<to_r)ret+=query(rs(x),mid+1,r,to_l,to_r);
    return ret;
}
il void modify_pre_sig(ri x,ri dat){modify(1,1,n,dfn[x],dfn[x],dat);}
il void modify_pre(ri x,ri dat){modify(1,1,n,dfn[x],low[x],dat);}
il int query_pre(ri x){ri ret=0;while(x)ret+=query(1,1,n,dfn[top[x]],dfn[x]),x=fa[top[x]];return ret;}

main()
{
//    freopen("3178.in","r",stdin);freopen("3178.out","w",stdout);
    n=read();q=read();rp(i,1,n)val[i]=read();rp(i,1,n-1){ri x=read(),y=read();ad(x,y);}dfs1(1,0);dfs2(1,1);build(1,1,n);
    while(q--)
    {
        ri op=read();
        switch(op)
        {
        case 1:{ri x=read(),a=read();modify_pre_sig(x,a);break;}
        case 2:{ri x=read(),a=read();modify_pre(x,a);break;}
        case 3:{ri x=read();printf("%lld\n",query_pre(x));break;}
        }
    }
    return 0;
}
只会做做小水题安慰下自己了QAQ

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/10658790.html