【BZOJ】4012: [HNOI2015]开店

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012


给出一个$n$个点的树,树上每一个点都有一个值$age$,每条边都有边权,每次查询一个点,求出树中所有点上权值${L<=age[i]<=R}$的点到它的距离的和。


为了学习传说中的动态树分治,我就把这个题当作模板题来写了。

当然这题也可以树链剖分+权值线段树

 

  为什么叫做动态树分治?其实就是把分治的结构记录了下来,树分治的好处在于每一次操作(找出当前块重心并再次递归)可以快速减少树的大小,我们记录下这个每次求出的树的重心的结构,这样的分治结构是严格log层的,每一次查询的是沿着分治结构构出的树往上跳,统计所有点到当前点的距离(这里需要数据结构维护,可以开一个vector动态记录每一个点在分治中所管辖的子树的所有点的信息,然后查询的时候二分即可),然后再往分治结构构成的树的父亲上跳,因为在分治结构的父亲所管辖的子树一定包含了当前点所管辖的子树,所以需要容斥(全是细节)。复杂度${O(nlog^{2})}$

  可怕的是BZOJ上似乎卡常?

 

 

 


code:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 #include<ctime>
  9 using namespace std;
 10 #define maxn 600100
 11 #define llg long long
 12 #define RG register llg 
 13 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 14 llg Q,A,n,m,age[maxn],ans,dad[maxn],dadv[maxn],maxage,f[maxn][21],dis[maxn][21],deep[maxn];
 15 bool bj[maxn],bj_[maxn];
 16 llg g[maxn<<1],maxl,weizhi,dl[maxn],tail,L,R,o,te,buf[50];
 17 
 18 inline void write(RG x)
 19 {
 20     if (x<0) putchar('-'),x=-x;
 21     buf[0]=0;
 22     while (x) buf[++buf[0]]=x%10,x/=10;
 23     if (!buf[0]) buf[0]=1,buf[1]=0;
 24     while (buf[0]) putchar('0'+buf[buf[0]--]);
 25     putchar('\n');
 26 }
 27 
 28 inline llg getint()
 29 {
 30     llg w=0,q=0;
 31     char c=getchar();
 32     while((c<'0' || c>'9') && c!='-') c=getchar();
 33     if (c=='-')  q=1, c=getchar();
 34     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
 35     return q ? -w : w;
 36 }
 37 
 38 struct edge{
 39     int y,next;
 40     llg d;
 41 }e[maxn<<1];
 42 
 43 void addedge(RG x,RG y,RG d){
 44     e[++te].y=y;
 45     e[te].d=d;
 46     e[te].next=g[x];
 47     g[x]=te;
 48 }
 49 
 50 struct node
 51 {
 52     llg age,dis,qz,qz_,dis_;
 53 };
 54 inline bool cmp(const node&a,const node&b) {return a.age<b.age;}
 55 
 56 vector<node>c[maxn];
 57 
 58 inline void clear_() {for (RG i=1;i<=tail;i++) bj_[dl[i]]=0; tail=0;}
 59 
 60 inline void dfs(RG x,RG fa)
 61 {
 62     for (RG i=g[x];i;i=e[i].next) 
 63     {
 64         RG v=e[i].y;
 65         if (v==fa) continue;
 66         f[v][0]=x; dis[v][0]=e[i].d;
 67         deep[v]=deep[x]+1;
 68         dfs(v,x);
 69     }
 70 }
 71 
 72 inline void make_f()
 73 {
 74     for (RG j=1;j<=17;j++)
 75         for (RG i=1;i<=n;i++)
 76         {
 77             f[i][j]=f[f[i][j-1]][j-1];
 78             dis[i][j]=dis[i][j-1]+dis[f[i][j-1]][j-1];
 79         }
 80 }
 81 
 82 inline llg find_dis(RG x,RG y)
 83 {
 84     if (x==0 || y==0) return 0;
 85     RG ans=0;
 86     if (deep[x]<deep[y]) swap(x,y);
 87     for (RG i=17;i>=0;i--)
 88         if (deep[f[x][i]]>=deep[y])
 89         {
 90             ans+=dis[x][i];
 91             x=f[x][i];
 92         }
 93     if (x==y) return ans;
 94     for (RG i=17;i>=0;i--)
 95         if (f[x][i]!=f[y][i])
 96         {
 97             ans+=dis[x][i]+dis[y][i];
 98             x=f[x][i],y=f[y][i];
 99         }
100     return ans+dis[x][0]+dis[y][0];
101 }
102 
103 void init()
104 {
105     RG x,y,z;
106     cin>>n>>Q>>A;
107     for (RG i=1;i<=n;i++) age[i]=getint(),maxage=max(maxage,age[i]);
108     for (RG i=1;i<n;i++)
109     {
110         x=getint(),y=getint(),z=getint();
111         addedge(x,y,z);
112         addedge(y,x,z);
113     }
114     deep[1]=1;
115     dfs(1,0);
116     make_f();
117 }
118 
119 inline llg find_size(RG x)
120 {
121     bj_[x]=1;
122     dl[++tail]=x;
123     RG tot=1;
124     for (RG i=g[x];i;i=e[i].next)
125     {
126         RG v=e[i].y;
127         if (bj[v] || bj_[v]) continue;
128         tot+=find_size(v);
129     }
130     return tot;
131 }
132 
133 inline llg dp(RG x,RG size)
134 {
135     bj_[x]=1;
136     dl[++tail]=x;
137     RG tot=1,ma=0;
138     for (register llg i=g[x];i;i=e[i].next)
139     {
140         RG v=e[i].y;
141         if (bj[v] || bj_[v]) continue;
142         RG he=dp(v,size);
143         ma=max(ma,he);
144         tot+=he;
145     }
146     ma=max(size-tot,ma);
147     if (ma<maxl)
148     {
149         maxl=ma;
150         weizhi=x;
151     }
152     return tot;
153 }
154 
155 inline  llg find_root(RG x)
156 {
157     clear_();
158     RG size=find_size(x);
159     clear_();
160     maxl=n+1; weizhi=-1;
161     dp(x,size);
162     return weizhi;
163 }
164 
165 inline void dfs_c(RG x,RG now)
166 {
167     bj_[x]=1; dl[++tail]=x;
168     node E;
169     E.age=age[x]; E.dis=find_dis(x,now); E.dis_= find_dis(x,dad[now]);
170     c[now].push_back(E);
171     for (RG i=g[x];i;i=e[i].next)
172     {
173         RG v=e[i].y;
174         if (bj[v] || bj_[v]) continue;
175         dfs_c(v,now);
176     }
177 }
178 
179 inline void solve( RG now,RG fa)
180 {
181     RG ne=find_root(now);
182     now=ne;
183      dadv[now]=find_dis(now,fa);
184     bj[now]=1;
185     dad[now]=fa;
186     clear_();
187     dfs_c(now,now);
188     for (RG i=g[now];i;i=e[i].next)
189     {
190         RG v=e[i].y;
191         if (bj[v]) continue;
192         solve(v,now);
193     }
194     RG si=c[now].size();
195     sort(c[now].begin(),c[now].end(),cmp);
196     c[now][0].qz=c[now][0].dis;
197     c[now][0].qz_=c[now][0].dis_;
198     for (RG i=1;i<si;i++) 
199     {
200         c[now][i].qz=c[now][i-1].qz+c[now][i].dis;
201         c[now][i].qz_=c[now][i-1].qz_+c[now][i].dis_;
202     }
203 }
204 
205 void read() {RG x,y; x=getint(),y=getint(); L=min((x+ans)%A,(y+ans)%A); R=max((x+ans)%A,(y+ans)%A);}
206 
207 inline llg erfen(RG x, RG V,RG dis_,bool pd)
208 {
209     RG l=0,r=c[x].size()-1,mid,wz=-1;
210     while (l<=r)
211     {
212         mid=(l+r)>>1;
213         if (c[x][mid].age<=V) {wz=mid; l=mid+1;}else{r=mid-1;}
214     }
215     if (wz==-1) return 0;
216     if (pd) return c[x][wz].qz+(dis_-find_dis(dad[x],o))*(wz+1)-c[x][wz].qz_;
217     else return c[x][wz].qz_+(wz+1)*(find_dis(dad[x],o)-dis_)-c[x][wz].qz;
218 }
219 
220 inline llg erfen_(RG x,RG V)
221 {    
222     RG l=0,r=c[x].size()-1,mid,wz=-1;
223     while (l<=r)
224     {
225         mid=(l+r)>>1;
226         if (c[x][mid].age<=V) {wz=mid; l=mid+1;}else{r=mid-1;}
227     }
228     if (wz==-1) return 0;
229     return (wz+1)*find_dis(dad[x],o)+c[x][wz].qz_;
230 }
231 
232 inline void find(register llg x)
233 {
234     RG dis_=find_dis(x,o);
235 //    llg sum=erfen(x,R,dis_)-erfen(x,L-1,dis_);
236 //    llg dec=erfen_(x,R)-erfen_(x,L-1);
237     ans+=erfen(x,R,dis_,1)+erfen(x,L-1,dis_,0);
238 //    ans+=sum-dec;
239     if (dad[x]!=0) find(dad[x]);
240 }
241 
242 llg dg(llg x)
243 {
244     if (dad[x]!=0) return dg(dad[x])+1;
245     else return 1;
246 }
247 
248 int main()
249 {
250     yyj("shop");
251     init();
252     solve(1,0);
253 /*    for (llg i=1;i<=n;i++) 
254     {
255         maxl=max(maxl,dg(i));
256     }
257     cout<<maxl; return 0;*/
258     while (Q--)
259     {
260         o=getint();
261         read();
262         ans=0;
263         find(o);
264         write(ans);
265     }
266 //    cout<<clock();
267     return 0;
268 }

 

posted @ 2017-02-12 11:37  №〓→龙光←  阅读(179)  评论(0编辑  收藏  举报