标签:
1 3 3 1 2 3 1 2 2 3
6HintIf you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
设分治中心为g, 我们只需要计算跨过g的答案, 其他的可以分治计算.
跨过根的可以容斥做, 没有限制的 - ∑端点落在同一颗子树上的. 上述两个过程是一样的, 于是只考虑没有限制的怎么做.
令x?i??,y?i??为i到g路径上的最大值和最小值. 我们按照x?i??排序, 然后枚举x?i??必选, 那么前面可选的x?j??,y?j??(j<i)必须要满足x?i???d≤x?j??,x?i???d≤y?j??, 由于x?j??≥y?j??, 只需要考虑x?i???d≤y?j??. 于是只要枚举x?i??然后用树状数组统计答案即可. 复杂度是O(nlog?2??n).
#define N 100050 #define M 100005 #define maxn 205 #define MOD 1000000000000000007 struct TreeNum{ int a[N],n; //树状数组模板 void init(int nn){ n = nn + 1; for(int i = 0;i<=n + 1;i++) a[i] = 0; } int lowbit(int x) { return x & (-x); } void modify(int x,int add)//一维 { while(x<=n) { a[x]+=add; x+=lowbit(x); } } int get_sum(int x) { if(x < 0) return 0; if(x > n) x = n; int ret=0; while(x!=0) { ret+=a[x]; x-=lowbit(x); } return ret; } }; int T,n,m,k,u,v,l,center,all,num,nodes[N],dp[N],xx[N],yy[N],pri[N],mymap[N],no; __int64 ans; bool vis[N]; vector<pii> p[N]; vector<pii> depV; TreeNum mytree; void findRoot(int root,int fa){ nodes[root] = 1;dp[root] = 0; FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ findRoot(g,root); nodes[root] += nodes[g]; dp[root] = max(dp[root],nodes[g]); } } dp[root] = max(dp[root],all - nodes[root]); if(dp[root] < num){ num = dp[root];center = root; } } int getRoot(int root,int sn){ num = INF;all = sn;center = root; findRoot(root,-1); return center; } void getDp(int root,int fa){ nodes[root] = 1; depV.push_back(mp(xx[root],root)); mymap[no++] = yy[root]; FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ xx[g] = max(xx[root],pri[g]); yy[g] = min(yy[root],pri[g]); getDp(g,root); nodes[root] += nodes[g]; } } } int getIndex(int x){ return lower_bound(mymap,mymap + no,x) - mymap; } __int64 cal(int root,bool isfirst){ depV.clear();no = 0; if(isfirst) xx[root] = pri[root],yy[root] = pri[root]; getDp(root,-1); sort(depV.begin(),depV.end()); sort(mymap,mymap + no); no = unique(mymap,mymap + no) - mymap; __int64 sum = 0; mytree.init(no); for(int i = 0;i < depV.size();i++){ int xi = depV[i].first,yi = yy[depV[i].second]; if(xi - yi <= k ){ int goal = getIndex(xi - k); sum += (__int64)(mytree.get_sum(no + 1) - mytree.get_sum(goal)); } mytree.modify(getIndex(yi) + 1,1); } return sum; } void work(int root,int fa){ vis[root] = true; ans += cal(root,true); FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ ans -= cal(g,false); work(getRoot(g,nodes[g]),-1); } } } int main() { while(S(T)!=EOF) { while(T--){ S2(n,k); ans = 0; FI(n) p[i + 1].clear(),vis[i + 1] = false; FI(n) scan_d(pri[i+1]); FI(n-1){ S2(u,v); p[u].push_back(mp(v,1)); p[v].push_back(mp(u,1)); } work(getRoot(1,n),-1); printf("%I64d\n",ans * 2); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/mengzhengnan/article/details/47177055