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 }
原文地址:https://www.cnblogs.com/fzmh/p/5423454.html