zoukankan      html  css  js  c++  java
  • bzoj4012 [HNOI2015]开店

      树分治。以递归的顺序建造一个重心树,每层用数组维护所有点按年龄从小到大排序后,其到当前层重心的前缀和。询问时在每一层算出需要经过该层重心才能到达查询点的距离和,累加就是答案,该操作可以用之前维护的信息来进行操作,具体看代码。复杂度O(nlogn^2)

      代码

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<vector>
      4 #include<set>
      5 #define fi first
      6 #define sc second
      7 #define pb push_back
      8 #define mp make_pair
      9 #define N 400010
     10 #define M 20000000
     11 #define lb(x) (x&-x)
     12 using namespace std;
     13 typedef long long ll;
     14 int a[N],n,m,i,tot,root,q,f[N];
     15 int dp,p[N],pre[N],tt[N],s[N],flag[N],ww[N],deep[N];
     16 int L[N],R[N],LL[N],RR[N];
     17 int jump[N][20];
     18 ll ans,dist[N];
     19 struct g{
     20     int v;ll dis;
     21     void set(int a,ll b)
     22     {
     23         v=a;
     24         dis=b;
     25     }
     26 }e[M];
     27 bool operator <(g a,g b){return a.v<b.v;}
     28 void link(int x,int y,int z)
     29 {
     30     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;ww[dp]=z;
     31 }
     32 void getroot(int x,int fa,int size)
     33 {
     34     int i=p[x],fg=0;
     35     s[x]=1;
     36     while (i)
     37     {
     38         if ((tt[i]!=fa)&&(!flag[tt[i]]))
     39         {
     40             getroot(tt[i],x,size);
     41             s[x]+=s[tt[i]];
     42             if (s[tt[i]]>size/2) fg=1;
     43         }
     44         i=pre[i];
     45     }
     46     if (size-s[x]>size/2) fg=1;
     47     if (!fg) root=x;    
     48 }
     49 void get(int x,int fa,ll dis)
     50 {
     51     int i=p[x];
     52     e[++tot].set(a[x],dis);
     53     while (i)
     54     {
     55         if ((!flag[tt[i]])&&(tt[i]!=fa))
     56             get(tt[i],x,dis+ww[i]);
     57         i=pre[i];
     58     }
     59 }
     60 int find(int x,int y)
     61 {
     62     int i=p[x];
     63     while (i)
     64     {
     65         if (tt[i]==y) return ww[i];
     66         i=pre[i];
     67     }
     68 }
     69 void dfs(int x,int fa,int size)
     70 {
     71     int i,rt,tx=x;
     72     getroot(x,0,size);
     73     x=root;f[x]=fa;
     74     flag[x]=1;
     75     i=p[x];
     76     while (i)
     77     {
     78         if (!flag[tt[i]])
     79         {
     80             if (s[tt[i]]<s[x])
     81                 dfs(tt[i],x,s[tt[i]]);
     82             else
     83                 dfs(tt[i],x,size-s[x]);
     84         }
     85         i=pre[i];
     86     }
     87     L[x]=tot+1;
     88     get(x,0,0);
     89     R[x]=tot;
     90     sort(e+L[x],e+1+R[x]);
     91     for (i=L[x]+1;i<=R[x];i++) e[i].dis+=e[i-1].dis;
     92     
     93     flag[x]=0;
     94     if (f[x])
     95     {
     96     LL[x]=tot+1;
     97     get(tx,f[x],find(f[x],tx));
     98     RR[x]=tot; 
     99     sort(e+LL[x],e+1+RR[x]);
    100     for (i=LL[x]+1;i<=RR[x];i++) e[i].dis+=e[i-1].dis;
    101     }
    102 }
    103 void gao(int x,int fa)
    104 {
    105     int i;
    106     deep[x]=deep[fa]+1;
    107     jump[x][0]=fa;
    108     for (i=1;i<=18;i++)
    109     jump[x][i]=jump[jump[x][i-1]][i-1];
    110     i=p[x];
    111     while (i)
    112     {
    113         if (tt[i]!=fa) 
    114         {
    115             dist[tt[i]]=dist[x]+ww[i];
    116             gao(tt[i],x);
    117         }
    118         i=pre[i];
    119     }
    120 }
    121 int lca(int a,int b)
    122 {
    123     int i;
    124     if (deep[a]<deep[b]) a^=b^=a^=b;
    125     for (i=18;i>=0;i--)
    126     if (deep[jump[a][i]]>=deep[b]) a=jump[a][i];
    127     if (a==b) return a;
    128     for (i=18;i>=0;i--)
    129     if (jump[a][i]!=jump[b][i])
    130     {
    131         a=jump[a][i];b=jump[b][i];
    132     }
    133     return jump[a][0];
    134 }
    135 pair<ll,ll> ef(int l,int r,int x)
    136 {
    137     int m,tmp=l;
    138     while (l<=r)
    139     {
    140         m=(l+r)>>1;
    141         if (e[m].v>x) r=m-1;else l=m+1;
    142     }
    143     ll dis=0;
    144     if (r>=tmp) dis=e[r].dis;
    145     return mp(r-tmp+1,dis);
    146 }
    147 ll query(int x,int a,int b)
    148 {
    149     int tx=x;
    150     ll ans=0;
    151     while (x)
    152     {
    153         pair<ll,ll> l=ef(L[x],R[x],a-1);
    154         pair<ll,ll> r=ef(L[x],R[x],b);
    155         ans+=r.sc-l.sc+(r.fi-l.fi)*(dist[tx]+dist[x]-2*dist[lca(tx,x)]);
    156     
    157         if (f[x])
    158         {
    159             pair<ll,ll> l=ef(LL[x],RR[x],a-1);
    160             pair<ll,ll> r=ef(LL[x],RR[x],b);
    161             ans-=(r.sc-l.sc+(r.fi-l.fi)*(dist[tx]+dist[f[x]]-2*dist[lca(tx,f[x])]));
    162         }
    163         x=f[x];    
    164     }
    165     return ans;
    166 }
    167 int main()
    168 {
    169     scanf("%d%d%d",&n,&q,&m);
    170     for (i=1;i<=n;i++) 
    171     //a[i]=0;
    172     scanf("%d",&a[i]); 
    173     for (i=1;i<n;i++)
    174     {
    175         int u,v,w;
    176         //u=i;v=i+1;w=1000;
    177         scanf("%d%d%d",&u,&v,&w);
    178         link(u,v,w);link(v,u,w);
    179     }
    180     dfs(1,0,n);
    181     deep[0]=-1;gao(1,0);
    182     for (i=1;i<=q;i++)
    183     {
    184         int u,v,w;
    185         scanf("%d%d%d",&u,&v,&w);
    186         int ql,qr;
    187         ql=min((v+ans)%m,(w+ans)%m);
    188         qr=max((v+ans)%m,(w+ans)%m);
    189         ans=query(u,ql,qr);
    190         printf("%lld
    ",ans);
    191     }
    192     
    193 }
  • 相关阅读:
    1094 纪念品分组
    1803 凌乱的yyy
    1181 数列分段1
    1223排队接水
    1616 疯狂的采药(完全背包问题)
    1305 新二叉树
    1280 尼克的任务
    1020 导弹拦截
    快速学会如何使用Shiro
    mysql 让清空表且自增的id重新从0开始的命令
  • 原文地址:https://www.cnblogs.com/fzmh/p/5423454.html
Copyright © 2011-2022 走看看