hdu 6162 离线树链剖分

来源:互联网 发布:nba本赛季数据 编辑:程序博客网 时间:2024/05/29 19:26

题意:一个树,点权,查询x到y路径上 价值在[a,b]之间的点的权值和


思路:剖分模板题,首先要想到离线处理,第一步将查询分为query(x,y,0,b)-query(x,y,0,a);接下来我们就发现了可以按照点权的大小以及查询a的大小离线处理,这样就相当于只查询query(x,y)。。。故直接上个剖分点权的模板


代码:

#include<bits/stdc++.h>using namespace std;#define ls (rt<<1)#define rs (rt<<1|1)#define mid (tr[rt].l+(tr[rt].r-tr[rt].l)/2)#define X first#define Y second#define PB push_back#define MP make_pair#define MEM(x,y) memset(x,y,sizeof(x));#define bug(x) cout<<"bug"<<x<<endl;typedef long long ll;const int maxn =1e5+100;#pragma comment(linker, "/STACK:1024000000,1024000000")typedef pair<int,pair<int,int> > pii;struct TREE{ll sum,l,r,tag;}tr[maxn*4];int pos[maxn],sz[maxn],top[maxn],son[maxn],fa[maxn],id[maxn],deep[maxn],cnt=0;vector<int> g[maxn];//void pushup(int rt){tr[rt].sum=tr[ls].sum+tr[rs].sum;}void build(int l,int r,int rt){    tr[rt].l=l,tr[rt].r=r;    if(l==r){tr[rt].sum=0;return ;}    int midd=l+(r-l)/2;    build(l,midd,ls),build(midd+1,r,rs);    tr[rt].sum=tr[ls].sum+tr[rs].sum;}void pushdown(int rt){    if(tr[rt].tag){        tr[ls].tag=(tr[ls].tag+tr[rt].tag);        tr[rs].tag=(tr[rs].tag+tr[rt].tag);        tr[ls].sum=(tr[ls].sum+(tr[ls].r-tr[ls].l+1)*tr[rt].tag);        tr[rs].sum=(tr[rs].sum+(tr[rs].r-tr[rs].l+1)*tr[rt].tag);        tr[rt].tag=0;    }}void update(int l,int r,int c,int rt){    if(l<=tr[rt].l&&tr[rt].r<=r){        tr[rt].sum=(tr[rt].sum+(c*(tr[rt].r-tr[rt].l+1)));        tr[rt].tag+=c;        return ;    }    pushdown(rt);    if(l<=mid) update(l,r,c,ls);    if(r>mid) update(l,r,c,rs);    tr[rt].sum=tr[ls].sum+tr[rs].sum;}ll query(int l,int r,int rt){    if(l<=tr[rt].l&&tr[rt].r<=r) return tr[rt].sum;    pushdown(rt);    ll ans=0;    if(l<=mid) ans+=query(l,r,ls);    if(r>mid) ans+=query(l,r,rs);    return ans;}void dfs1(int x,int fat,int dep){    deep[x]=dep,fa[x]=fat,sz[x]=1;    for(int i=0;i<g[x].size();i++){        int v=g[x][i];        if(v!=fat){            dfs1(v,x,dep+1);            sz[x]+=sz[v];            if(son[x]==-1||sz[son[x]]<sz[v]) son[x]=v;        }    }}void dfs2(int x,int tp){    top[x]=tp;pos[x]=++cnt;id[pos[x]]=x;    if(son[x]==-1) return ;    dfs2(son[x],tp);    for(int i=0;i<g[x].size();i++){        int v=g[x][i];        if(v!=fa[x]&&v!=son[x])            dfs2(v,v);    }}ll add(int t1,int t2,int c,int ok){    ll u=t1,v=t2,ans=0;    //bug("F")    while(top[u]!=top[v]){        if(deep[top[u]]>deep[top[v]]) swap(u,v);        if(!ok)update(pos[top[v]],pos[v],c,1);        else ans+=query(pos[top[v]],pos[v],1);        v=fa[top[v]];    }    if(deep[u]>deep[v]) swap(u,v);//!!    if(!ok) update(pos[u],pos[v],c,1);    else ans+=query(pos[u],pos[v],1);    return ans;}int a[maxn];pii Q[maxn*3];int ql[maxn],qr[maxn],qll[maxn],qrr[maxn];ll ans[maxn];int main(){    int n,P,v,u;    while(scanf("%d%d",&n,&P)!=EOF){        memset(son,-1,sizeof(son));        MEM(ans,0);        for(int i=0;i<=n+5;i++) g[i].clear();        int x,y,num=0;        cnt=0;        for(int i = 1; i <= n; i++){            scanf("%d",&a[i]);            Q[num++]=MP(a[i],MP(0,i));        }        for(int i=1;i<n;i++){            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        dfs1(1,-1,1);        dfs2(1,1);        build(1,n,1);        for(int i = 1; i <=P; i++){            scanf("%d%d%d%d",&ql[i],&qr[i],&qll[i],&qrr[i]);            Q[num++]=MP(qll[i],MP(-1,i));            Q[num++]=MP(qrr[i],MP(1,i));        }        sort(Q,Q+num);        //bug(1)        for(int i=0;i<num;i++){            int ii=Q[i].Y.Y;            if(Q[i].Y.X==0)add(ii,ii,Q[i].X,0);            else if(Q[i].Y.X==-1)ans[ii]-=add(ql[ii],qr[ii],0,1);            else ans[ii]+=add(ql[ii],qr[ii],0,1);        }        for(int i = 1; i <=P; i++)            printf("%lld%c",ans[i]," \n"[i==P]);    }    return 0;}


原创粉丝点击