• P3241 [HNOI2015]开店


    题解:动态点分治

    建立点分树

    每个点维护点分树子树内节点到这个节点和父亲节点距离的前缀和

    二分查找锁定合法区间

    对每个祖先分治中心查询路径和然后减去不合法子树内的路径和

    注意:求大量LCA时用树剖

    不开O2时少用STL

    相乘炸int

    lower_bound和upper_bound返回值边界

    注意常数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn=200009;
    const int oo=1000000000;
    typedef long long Lint;
    
    int n,T,u;
    int a[maxn];
    
    int cntedge;
    int head[maxn];
    int to[maxn<<1],nex[maxn<<1],dist[maxn<<1];
    void Addedge(int x,int y,int z){
        nex[++cntedge]=head[x];
        to[cntedge]=y;
        dist[cntedge]=z;
        head[x]=cntedge;
    }
    
    int nowsiz,root;
    int vis[maxn];
    int siz[maxn],g[maxn];
    void Getsiz(int x,int fa){
        siz[x]=1;
        for(int i=head[x];i;i=nex[i]){
            if(vis[to[i]])continue;
            if(to[i]==fa)continue;
            Getsiz(to[i],x);
            siz[x]+=siz[to[i]];
        }
    }
    void Getroot(int x,int fa){
        siz[x]=1;
        g[x]=0;
        for(int i=head[x];i;i=nex[i]){
            if(vis[to[i]])continue;
            if(to[i]==fa)continue;
            Getroot(to[i],x);
            siz[x]+=siz[to[i]];
            g[x]=max(g[x],siz[to[i]]);
        }
        g[x]=max(g[x],nowsiz-siz[x]);
        if(g[x]<g[root])root=x;
    }
    
    int divfa[maxn];
    void Sol(int x){
        vis[x]=1;
        Getsiz(x,0);
        for(int i=head[x];i;i=nex[i]){
            if(vis[to[i]])continue;
            root=0;nowsiz=siz[to[i]];
            Getroot(to[i],x);
            divfa[root]=x;
            Sol(root);
        }
    }
    
    int father[maxn],dep[maxn],d[maxn],top[maxn],hson[maxn];
    void Dfs(int x,int fa){
        father[x]=fa;
        dep[x]=dep[fa]+1;
        siz[x]=1;
        for(int i=head[x];i;i=nex[i]){
            if(to[i]==fa)continue;
            d[to[i]]=d[x]+dist[i];
            Dfs(to[i],x);
            siz[x]+=siz[to[i]];
            if(siz[to[i]]>siz[hson[x]])hson[x]=to[i];
        }
    }
    void Dfs2(int x,int toppoint){
    	top[x]=toppoint;
    	if(!hson[x])return;
    	Dfs2(hson[x],toppoint);
    	for(int i=head[x];i;i=nex[i]){
    		if(to[i]==father[x])continue;
    		if(to[i]==hson[x])continue;
    		Dfs2(to[i],to[i]);
    	}
    }
    
    int Getlca(int u,int v){
    	int tu=top[u];
    	int tv=top[v];
    	while(tu!=tv){
    		if(dep[tu]<dep[tv]){
    			swap(u,v);
    			swap(tu,tv);
    		}
    		u=father[tu];
    		tu=top[u];
    	}
    	if(dep[u]<dep[v])return u;
    	else return v;
    }
    
    int Getdist(int x,int y){
        if((x==0)||(y==0))return 0;
        int lca=Getlca(x,y);
        return d[x]+d[y]-d[lca]-d[lca];
    }
    
    vector<int>G[maxn];
    vector<Lint>S[maxn];
    vector<Lint>S2[maxn];
    
    int cmp(const int &rhs1,const int &rhs2){
        return a[rhs1]<a[rhs2];
    }
    
    int main(){
        scanf("%d%d%d",&n,&T,&u);
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        for(int i=1;i<n;++i){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Addedge(x,y,z);
            Addedge(y,x,z);
        }
        
        Dfs(1,0);
        Dfs2(1,1);
        
        g[0]=oo;root=0;nowsiz=n;
        Getroot(1,0);
        Sol(root);
        
        for(int i=1;i<=n;++i){
            int x=i;
            while(x){
                G[x].push_back(i);
                x=divfa[x];
            }
        }
        
    //	for(int i=1;i<=n;++i){
    //		for(int j=1;j<=n;++j){
    //			cout<<Getdist(i,j)<<' ';
    //		}
    //		cout<<endl;
    //	}
        for(int i=1;i<=n;++i){
            sort(G[i].begin(),G[i].end(),cmp);
            Lint now=0,now2=0;
            for(int j=0;j<G[i].size();++j){
                now=now+Getdist(i,G[i][j]);
                now2=now2+Getdist(divfa[i],G[i][j]);
                S[i].push_back(now);
                S2[i].push_back(now2);
                G[i][j]=a[G[i][j]];
            }
    //		printf("=->%d %d %d
    ",i,now,now2);
        }
    //	for(int i=1;i<=n;++i)cout<<d[i]<<' ';
    //	cout<<endl;
        Lint ans=0;
        while(T--){
            int x,y,Lold,Rold;
            scanf("%d%d%d",&x,&Lold,&Rold);
            y=x;
            int t1=(Lold+ans)%u;
            int t2=(Rold+ans)%u;
            Lold=min(t1,t2);
            Rold=max(t1,t2);
    //		cout<<Lold<<' '<<Rold<<endl;
            ans=0;
            int p=0;
    //		cout<<ans<<endl;
    //		for(int i=0;i<G[x].size();++i)cout<<G[x][i]<<' ';
    //		cout<<endl;
            p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
            if(p>-1)ans+=S[x][p];
    //		cout<<p<<endl;
            p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
            if(p)ans-=S[x][p-1];
    //		cout<<p<<endl;
    //		cout<<ans<<endl;
            while(divfa[x]){
                Lint fdist=Getdist(divfa[x],y);
                int fa=divfa[x];
                
                p=upper_bound(G[fa].begin(),G[fa].end(),Rold)-G[fa].begin()-1;
                if(p>-1)ans+=S[fa][p]+fdist*(p+1);
    //			cout<<p<<' ';
                p=lower_bound(G[fa].begin(),G[fa].end(),Lold)-G[fa].begin();
                if(p)ans-=S[fa][p-1]+fdist*p;
    //			cout<<p<<endl;
    //			cout<<ans<<endl;
                p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
                if(p>-1)ans-=S2[x][p]+fdist*(p+1);
                p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
                if(p)ans+=S2[x][p-1]+fdist*p;
    //			cout<<ans<<endl;
                x=divfa[x];
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    MySQL令人咋舌的隐式转换
    MySQL 数据库基础(二)(MySQL 服务基础与使用 MySQL 数据库)
    以友盟+U-Push为例,深度解读消息推送的筛选架构解决方案应用与实践
    逆向工程,调试Hello World !程序(更新中)
    520了,用32做个简单的小程序
    postgresql 数据库 update更新慢的原因(已解决)
    面试题单例模式的五种写法(枚举妙用)
    人工智能能力提升指导总结
    数据结构-队列(2)-循环队列
    数据结构-队列(1)
  • 原文地址:https://www.cnblogs.com/zzyer/p/8480624.html
Copyright © 2020-2023  润新知