BZOJ 1468 Tree 【模板】树上点分治

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define N 50010
 4 #define M 500010
 5 #define rg register
 6 #define LL long long
 7 using namespace std;
 8 int n,m,cnt,root,tot,totnow,totbf;
 9 int last[N],size[N],mxsize[N],dep[N],tmp[N],mg[N];
10 LL ans=0;
11 bool v[N];
12 struct edge{
13     int to,pre,dis;
14 }e[M];
15 inline int read(){
16     int k=0,f=1; char c=getchar();
17     while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
18     while(‘0‘<=c&&c<=‘9‘)k=k*10+c-‘0‘,c=getchar();
19     return k*f;
20 }
21 void getroot(int x,int fa){
22     size[x]=1; mxsize[x]=0;
23     for(rg int i=last[x],to;i;i=e[i].pre)if(!v[to=e[i].to]&&to!=fa){
24         getroot(to,x); size[x]+=size[to];
25         mxsize[x]=max(mxsize[x],size[to]);
26     }
27     mxsize[x]=max(mxsize[x],cnt-mxsize[x]);
28     if(!root||mxsize[x]<mxsize[root]) root=x;
29 }
30 void getdep(int x,int fa,int d){
31     dep[++totnow]=d;
32     for(rg int i=last[x],to;i;i=e[i].pre)
33         if(!v[to=e[i].to]&&to!=fa) getdep(to,x,d+e[i].dis);
34 }
35 void dfs(int x){
36     v[x]=1; totbf=1; tmp[1]=0;
37     for(rg int i=last[x],to;i;i=e[i].pre)if(!v[to=e[i].to]){
38         totnow=0; getdep(to,x,e[i].dis); sort(dep+1,dep+1+totnow);
39         int p=1;
40         for(rg int j=totbf;j;j--){
41             while(p<=totnow&&tmp[j]+dep[p]<=m) p++;
42             ans+=p-1;
43         }
44         p=1; int p2=1,totmg=0;
45         while(p<=totnow&&p2<=totbf)
46             mg[++totmg]=dep[p]<tmp[p2]?dep[p++]:tmp[p2++];
47         while(p<=totnow) mg[++totmg]=dep[p++];
48         while(p2<=totbf) mg[++totmg]=tmp[p2++];
49         for(rg int j=1;j<=totmg;j++) tmp[j]=mg[j];
50         totbf=totmg;
51     }
52     for(rg int i=last[x],to;i;i=e[i].pre)if(!v[to=e[i].to]){
53         root=0; cnt=size[to];
54         getroot(to,x); dfs(root);
55     }
56 }
57 int main(){
58     n=read();
59     for(rg int i=1;i<n;i++){
60         int u=read(),v=read(),w=read();
61         e[++tot]=(edge){v,last[u],w}; last[u]=tot;
62         e[++tot]=(edge){u,last[v],w}; last[v]=tot;
63     }
64     m=read();
65     cnt=n; getroot(1,0); dfs(root);
66     printf("%lld\n",ans);
67 }

  

原文地址:https://www.cnblogs.com/DriverLao/p/8856425.html

时间: 2024-10-08 15:45:46

BZOJ 1468 Tree 【模板】树上点分治的相关文章

bzoj 1468 Tree(点分治模板)

1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1527  Solved: 818[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k Output 一行,有多少对点之间的距离小于等于k Sample Input 7 1 6 13 6

[bzoj 1468] Tree

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1468 Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1517  Solved: 812[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

BZOJ.1468.Tree(点分治)

题目链接 BZOJ1468 POJ1741 题意: 计算树上距离<=K的点对数 我们知道树上一条路径要么经过根节点,要么在同一棵子树中. 于是对一个点x我们可以这样统计: 计算出所有点到它的距离dep[],排序后可以O(n)求得<=K的点对数量. 但画个图后我们可以发现,对于在同一棵子树中的路径被重复计算过了.于是我们Ans-=Calc(v),减去一棵子树中的路径答案,但是这并不是之前x到它们的路径,于是给v的dep[]设一个初始值为w(x->v路径权值). 这样x的答案就计算完了,将这

POJ-1741 Tree (树上点分治)

题目大意:一棵带边权无根树,边权代表距离,求距离小于等于k的点对儿数. 题目分析:这两个点之间的路径只有两种可能,要么经过根节点,要么在一棵子树内.定义depth(i)表示点 i 到根节点的距离,belong(i)表示 i 所属的子树.如果路径经过根节点,那么满足depth(i)+depth(j)<=k并且belong(i)<>belong(j)的(i,j)为一个点对儿,如果在子树内,递归到子树即可. 总的过程就变成了这样的: 1.求出所有的depth: 2.求出满足depth(i)+d

洛谷 P2634 BZOJ 2152 【模板】点分治(聪聪可可)

题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏. 他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个“点”,并用n-1条“边”把这n个“点”恰好连通(其实这就是一棵树).并且每条“边”上都有一个数.接下来由聪聪和可可分别随即选一个点(当然他们选点时是看不到这棵树的),如果两个点之间所有边上数的和

点分治专题——bzoj 1468 &amp;bzoj 2152 题解

[前言]最近一直在忙着学算法,但是效果似乎不是很好.前段时间的树剖也快忘了= =.树套树没熟练,就开始写主席树了= =.更别说本身就不是很懂的莫比乌斯反演了.~~决定好好复习一下. [点分治的作用]套用SYC大神的话说是:用来解决树上路径点权统计问题. [大致流程] ①找出这颗树的重心. ②统计经过这个重心的答案 ③用重心把树割开 ④对每个"小树"做同样的事 [Q1--重心]其实找重心再进行计算只是为了不被卡链.什么是重心?就是当前树中的一个点K,使得MAX(SON[K])最小.SON

树上点分治 poj 1741

Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k. Wri

poj2114 寻找树上存在长度为k点对,树上的分治

寻找树上存在长度为k点对,树上的分治  代码和  这个  差不多 ,改一下判断的就好 #include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <string.h> using namespace std; const int maxn=10004; int H[maxn],nx[maxn*2],to[maxn*2],numofE,d

AC日记——【模板】点分治(聪聪可可) 洛谷 P2634

[模板]点分治(聪聪可可) 思路: 点分治: (感谢灯神) 代码: #include <bits/stdc++.h> using namespace std; #define maxn 20005 #define INF 0x7fffffff int n,m,sum,num,cnt,ans,L,root,t; int head[maxn],vis[maxn],d[maxn]; int size[maxn],lar[maxn],flag[4]; int E[maxn<<1],V[ma