zoukankan      html  css  js  c++  java
  • BZOJ 4012 [HNOI2015]开店 (树分治+二分)

    题目大意:

    给你一棵树,边有边权,点有点权,有很多次询问,求点权$in[l,r]$的所有节点到某点$x$的距离之和,强制在线

    感觉这个题应该放在动态点分之前做= =

    套路方法和动态点分是一样的

    每次询问,从$x$开始,沿着点分树的树链向上统计,计算当前点的点分树的答案,然后去掉包含$x$的那棵点分子树的答案

    $x$节点在点分树内的 所有祖先节点 对于答案的贡献都有两个部分

    1.除了包含$x$的点分子树 的所有权值$in[l,r]$的节点到 当前祖先节点 的距离

    2.合法节点数量*当前祖先节点到$x$的距离

    而这道题是静态的,不用每个节点都开线段树,改成$vector$,每次都在上面二分就好了

    具体实现

    每个节点都开一个$vector$,设当前的点分节点是$x$,把$x$点分树内的所有子节点推进去,按照点权排序,再统计一下到$x$距离的前缀和

    统计$[l,r]$的答案时,只需要在$vector$里二分出右端点查询dis的前缀和,还要加上点数总和(即右端点下标) *当前 点分树节点 到 询问节点 的距离,再利用前缀和容斥$calc(r)-calc(l-1)$即可

    时间仍然是$O(nlog^{2}n)$,但空间变成了$O(nlogn)$

    由于用了$vector$常数大的一批但我也懒得优化了

      1 #include <vector>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 150100
      6 #define ll long long
      7 #define dd double
      8 #define inf 0x3f3f3f3f3f3f3f3fll
      9 using namespace std;
     10 
     11 int gint()
     12 {
     13     int ret=0,fh=1;char c=getchar();
     14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     16     return ret*fh;
     17 }
     18 
     19 struct Edge{
     20 int to[N1<<1],nxt[N1<<1],val[N1<<1],head[N1],cte;
     21 void ae(int u,int v,int w){
     22     cte++;to[cte]=v;val[cte]=w;
     23     nxt[cte]=head[u];head[u]=cte;}
     24 }e;
     25 namespace tr{
     26 ll dis[N1];int dep[N1],ff[N1<<1][20],lg[N1<<1],st[N1<<1],tot;
     27 void dfs1(int u,int dad)
     28 {
     29     st[u]=++tot; ff[tot][0]=u;
     30     for(int j=e.head[u];j;j=e.nxt[j])   
     31     {
     32         int v=e.to[j]; if(v==dad) continue;
     33         dis[v]=dis[u]+e.val[j]; dep[v]=dep[u]+1;
     34         dfs1(v,u); ff[++tot][0]=u;
     35     }
     36 }
     37 void get_st()
     38 {
     39     int i,j;
     40     for(lg[1]=0,i=2;i<=tot;i++) lg[i]=lg[i>>1]+1;
     41     for(j=1;j<=lg[tot];j++)
     42         for(i=1;i+(1<<j)-1<=tot;i++)
     43         ff[i][j]=dep[ ff[i][j-1] ] < dep[ ff[i+(1<<(j-1))][j-1] ] ? ff[i][j-1] : ff[i+(1<<(j-1))][j-1];
     44 }
     45 ll Dis(int x,int y)
     46 {
     47     int tx=min(st[x],st[y]),ty=max(st[x],st[y]),L=ty-tx+1;
     48     int fa=dep[ ff[tx][lg[L]] ] < dep[ ff[ty-(1<<lg[L])+1][lg[L]] ] ? ff[tx][lg[L]] : ff[ty-(1<<lg[L])+1][lg[L]];
     49     return dis[x]+dis[y]-2ll*dis[fa];
     50 }
     51 void init(){dfs1(1,-1);get_st();}
     52 };
     53 int n,m,ma;
     54 int ms[N1],sz[N1],use[N1],fr[N1],fa[N1],a[N1],tsz,G;
     55 void gra(int u,int dad)
     56 {
     57     sz[u]=1; ms[u]=0;
     58     for(int j=e.head[u];j;j=e.nxt[j])
     59     {
     60         int v=e.to[j]; if(v==dad||use[v]) continue;
     61         gra(v,u);
     62         sz[u]+=sz[v]; ms[u]=max(ms[u],sz[v]);
     63     }
     64     ms[u]=max(ms[u],tsz-sz[u]);
     65     if(ms[u]<ms[G]) G=u;
     66 }
     67 int que[N1],hd,tl;
     68 ll dis[N1];
     69 struct node{int id;ll sum;};
     70 vector<node>rm[N1],rf[N1];
     71 int cmp(node x,node y){return a[x.id]<a[y.id];}
     72 void bfs_add(int u,int g)
     73 {
     74     int j,v; hd=tl=1; que[hd]=u; fr[u]=0; dis[u]=0;
     75     while(hd<=tl)
     76     {
     77         u=que[hd++]; rm[g].push_back((node){u,dis[u]}); 
     78         for(j=e.head[u];j;j=e.nxt[j])
     79         {
     80             v=e.to[j]; if(use[v]||v==fr[u]) continue;
     81             fr[v]=u; dis[v]=dis[u]+e.val[j]; 
     82             que[++tl]=v;
     83         }
     84     }
     85     sort(rm[g].begin(),rm[g].end(),cmp);
     86     for(j=1;j<rm[g].size();j++)
     87         rm[g][j].sum+=rm[g][j-1].sum;
     88 }
     89 void bfs_sub(int u,int g)
     90 {
     91     int j,v; hd=tl=1; que[hd]=u; 
     92     while(hd<=tl)
     93     {
     94         u=que[hd++]; rf[g].push_back((node){u,dis[u]}); 
     95         for(j=e.head[u];j;j=e.nxt[j])
     96         {
     97             v=e.to[j]; if(use[v]||v==fr[u]) continue;
     98             que[++tl]=v;
     99         }
    100     }
    101     sort(rf[g].begin(),rf[g].end(),cmp);
    102     for(j=1;j<rf[g].size();j++)
    103         rf[g][j].sum+=rf[g][j-1].sum;
    104 }
    105 void main_dfs(int u)
    106 {
    107     use[u]=1; bfs_add(u,u);
    108     for(int j=e.head[u];j;j=e.nxt[j])
    109     {
    110         int v=e.to[j]; if(use[v]) continue;
    111         G=0; tsz=sz[v]; gra(v,-1); bfs_sub(v,G); fa[G]=u;
    112         main_dfs(G);
    113     }
    114 }
    115 using tr::Dis;
    116 ll calc(vector<node>&s,int lim,int &sum,int type)
    117 {
    118     int l=0,r=s.size()-1,mid,ans=-1;
    119     while(l<=r)
    120     {
    121         mid=(l+r)>>1;
    122         if(a[s[mid].id]<=lim) l=mid+1,ans=mid;
    123         else r=mid-1;
    124     }
    125     if(ans==-1) return 0;
    126     sum+=type*(ans+1);
    127     return s[ans].sum;
    128 }
    129 ll solve(int x,int L,int R)
    130 {
    131     ll ans=0;int sum;
    132     for(int i=x;i;i=fa[i])
    133     {
    134         sum=0;
    135         ans+=calc(rm[i],R,sum,1)-calc(rm[i],L-1,sum,-1);
    136         ans+=sum*Dis(x,i);
    137         if(!fa[i]) continue;
    138         sum=0;
    139         ans-=calc(rf[i],R,sum,1)-calc(rf[i],L-1,sum,-1);
    140         ans-=sum*Dis(x,fa[i]);
    141     }
    142     return ans;
    143 }
    144 
    145 int main()
    146 {
    147     scanf("%d%d%d",&n,&m,&ma);
    148     int i,j,x,y,w,A,B,l,r;ll ans=0;
    149     for(i=1;i<=n;i++) a[i]=gint();
    150     for(i=1;i<n;i++) x=gint(), y=gint(), w=gint(), e.ae(x,y,w), e.ae(y,x,w);
    151     tr::init();
    152     tsz=ms[0]=n; G=0; gra(1,-1); gra(G,-1); 
    153     main_dfs(G);
    154     for(j=1;j<=m;j++)
    155     {
    156         x=gint(); A=gint(); B=gint();
    157         l=(ans+A)%ma; r=(ans+B)%ma; if(l>r) swap(l,r);
    158         ans=solve(x,l,r);
    159         printf("%lld
    ",ans);
    160     }
    161     return 0;
    162 }
  • 相关阅读:
    Jenkins-在windows上配置自动化部署(Jenkins+Gitblit)
    GIT-Linux(CentOS7)系统部署GitLab服务器
    VMware 安装Linux系统 CentOS
    GIT-windows系统下Gitblit的使用方式
    SQL 显示所有表所占存储空间
    通过JavaScript更新UpdatePanel备忘
    Entity Framework调用表值函数实现全文检索?
    转载:javascript 拖拽排序,简洁示例备忘
    c++ 读写注册表
    MSSQL中建立分区表(转载备忘)
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10202105.html
Copyright © 2011-2022 走看看