NC15505. 抓fafa的qzh
描述
冬天又过去了,春天又来了,Alice和Bob又开始玩游戏了(雾
Alice和Bob开始玩一个小游戏,但他们觉得并不好玩,于是把这个游戏给了最可爱的fafa和最坏坏的qzh,fafa和qzh觉得很有趣,就玩了起来
这是在一棵树上的游戏,树的形态将会给出,所有树的边长度都为1
最可爱的fafa拥有一种高端的技巧,可以将自己化身为多个可爱度不同的fafa,每次轮到fafa行动时,fafa都会在点u到点v路径上所有的点都放一只可爱度为w的fafa,每个点可以同时存在多个fafa
最坏坏的qzh不喜欢可爱的生物,于是他要去抓可爱度l到可爱度r的fafa。起初qzh站在点p上,他想要知道他离所有可爱度为l到r的fafa的距离和到底是多少来决定他要不要离开他的笔记本
注意:因为fafa本体非常强大,所以坏坏的qzh并不能真的去抓fafa,也就是说,树上的fafa会不断增多,但坏坏的qzh只能看着这棵树越来越可爱,以及想(y)象(y)着去抓可爱的fafa
坏坏的qzh觉得很不开心,而且他的笔记本和脑子跑的都很慢,并不能解决这个问题,所以他把这个问题交给了你,你需要回答他每次询问的距离和是多少
输入描述
第一行输入两个数n,m,分别表示数的点数和询问的次数
第2行到第n行共计n-1行每行输入两个数a,b,表示点a和点b之间有一条边(数据保证是一棵树)
接下来m行,每行第一个数为1或者2,表示两种操作
1:读入u,v,w,表示在点u到点v的路径上都放一只可爱度为w的fafa
2:读入l,r,p,表示一只站在点p上的qzh想知道他距离所有可爱度为l到r之间([l,r])的距离和是多少
输出描述
输出若干行,每行包括一个整数,对于每个操作2需要输出,但操作1不需要
示例1
输入:
10 20 6 7 1 2 5 4 1 3 10 8 7 9 1 8 1 4 2 6 1 5 1 27280262 1 2 4 27245688 2 27234840 27290934 6 1 10 6 27227228 2 27313334 27321446 3 1 9 10 27258713 1 3 4 27249714 2 27270810 27309316 1 1 9 2 27254034 2 27292791 27302394 10 1 7 5 27319311 1 5 6 27301947 1 10 1 27318014 2 27247634 27320484 9 1 10 5 27299018 2 27240281 27286743 8 2 27296751 27319246 4 2 27309633 27314750 9 2 27257490 27301409 6 2 27235007 27294034 2
输出:
15 0 3 0 112 46 20 0 38 32
C++11(clang++ 3.9) 解法, 执行用时: 5473ms, 内存消耗: 48232K, 提交时间: 2018-04-07 15:48:33
#include<bits/stdc++.h> using namespace std; #define FOR(a,b,c) for(int a=(b),a##_end__=(c);a<a##_end__;++a) #define DOR(a,b,c) for(int a=(b)-1,a##_end__=(c);a>=a##_end__;--a) #define ll long long template<class T>inline bool chkmin(T&a,T const&b){return a>b?a=b,true:false;} template<class T>inline bool chkmax(T&a,T const&b){return a<b?a=b,true:false;} const int M=100005; const int S=1200; const int N=M/S+5; const int K=18; struct Node{int u,v,x;}Q[M]; vector<int> E[M]; int Log2[M<<1],ST[M<<1][K],Eulorn[M],Dep[M]; int dfsv[M],Fa[M],P[M]; ll Val[N][M],dp[M],APS[M]; int n,m,w,q,Eulor_cnt,dfn_cnt; void dfs(int u,int fa){ ST[++Eulor_cnt][0]=u; dfsv[++dfn_cnt]=u; Eulorn[u]=Eulor_cnt; for(auto v:E[u]) if(v^fa){ Fa[v]=u; Dep[v]=Dep[u]+1; dfs(v,u); ST[++Eulor_cnt][0]=u; } } inline int dep_min(int u,int v){return Dep[u]<Dep[v]?u:v;} void ST_table(){ FOR(k,1,K) FOR(i,1,(n<<1)-(1<<k)+1) ST[i][k]=dep_min(ST[i][k-1],ST[i+(1<<k-1)][k-1]); } inline int LCA(int u,int v){ u=Eulorn[u],v=Eulorn[v]; if(u>v) swap(u,v); int k=Log2[v-u+1]; return dep_min(ST[u][k],ST[v-(1<<k)+1][k]); } inline ll Query(int u,int v,int x){ int o=LCA(u,v),p=LCA(u,x),q=LCA(v,x),r=LCA(o,x); if(Dep[p]<Dep[q]) swap(p,q),swap(u,v); int Do=Dep[o],Du=Dep[u],Dv=Dep[v],Dp=Dep[p]; int sum=Du+Dv-(Do<<1)+1; if(o!=r) return (ll)(Do+Dep[x]-(Dep[r]<<1))*sum+APS[Dv-Do]+APS[Du-Do]; return (ll)(Dep[x]-Dp)*sum+APS[Du-Dp]+APS[Dp+Dv-(Do<<1)]; } void build(Node *Q,ll *Val){ FOR(i,0,M) P[i]=dp[i]=Val[i]=0; FOR(i,0,S){ int u=Q[i].u,v=Q[i].v,x=LCA(u,v); P[u]++,P[v]++,P[x]--,P[Fa[x]]--; } DOR(i,n+1,1){ int u=dfsv[i],v=Fa[u]; P[v]+=P[u]; dp[v]+=dp[u]+=P[u]; Val[v]+=Val[u]+dp[u]; } FOR(i,1,n+1){ int u=dfsv[i]; Val[u]=Val[Fa[u]]+dp[1]-(dp[u]<<1); } } int main(){ FOR(i,2,M<<1) Log2[i]=Log2[i>>1]+1; FOR(i,0,M) APS[i]=(ll)i*(i+1)>>1; scanf("%d %d",&n,&q); FOR(i,1,n){ int u,v; scanf("%d %d",&u,&v); E[u].push_back(v); E[v].push_back(u); } dfs(1,-1); ST_table(); while(q--){ int op,x,y,z; scanf("%d %d %d %d",&op,&x,&y,&z); if(op&1){ Q[w++]={x,y,z}; if(w%S==0){ auto cmp=[](Node A,Node B){return A.x<B.x;}; sort(Q+m,Q+w,cmp); inplace_merge(Q,Q+m,Q+w,cmp); FOR(i,0,(m=w)/S) build(Q+i*S,Val[i]); } } else{ ll res=0; FOR(i,m,w) if(x<=Q[i].x && Q[i].x<=y) res+=Query(Q[i].u,Q[i].v,z); int L=lower_bound(Q,Q+m,x,[](Node A,int x){return A.x<x;})-Q; int R=upper_bound(Q,Q+m,y,[](int x,Node A){return x<A.x;})-Q; if(L/S==R/S) FOR(i,L,R) res+=Query(Q[i].u,Q[i].v,z); else{ FOR(i,L/S+1,R/S) res+=Val[i][z]; FOR(i,L,L/S*S+S) res+=Query(Q[i].u,Q[i].v,z); FOR(i,R/S*S,R) res+=Query(Q[i].u,Q[i].v,z); } printf("%lld\n",res); } } return 0; }