标签:
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