• hdu 6162 离线树链剖分


    题意:一个树,点权,查询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]," 
    "[i==P]);
        }
        return 0;
    }


  • 相关阅读:
    霓虹灯牌 V0.3已发布
    ACSL比赛的鸡肋解释器???
    Linux和Aix系统shell获取IP地址
    openWrt编译环境feeds update a
    openWrt(LEDE)下载包目录dl目录新旧差异脚本备份,阿里百度更新下载连接
    20年5月面试汇总
    Redis++:(雪崩、击穿、穿透) 那点事
    Redis++:为什么Redis 是单线程却能支撑高并发?
    Java++:HikariCP连接池参数解释
    我来谈谈“人工智能”这个词给我带来了哪些想法
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672494.html
Copyright © 2020-2023  润新知