给定一棵n个点并且有边权的树,每个点的权值为该点能走的最远长度,并输入m个询问,每次询问最多有多少个编号连续的点,他们的最大最小点权差小于等于Q。N<=50000 M<=500 Q<=10000000
我们知道一个点能走的最远端点一定是树的直径的端点,所以我们只需从树的直径两端点dfs,就可以求出每个点能到的最远长度。。然后rmq+尺取即可。
这道题如果用系统的log会tle,所以必须手打log2。原理会再放一篇博客。
1 #include <cctype> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 const int maxn=50005, maxmi=18, INF=1e9; 9 //const double exp=1e-6; 10 int n, m, cntedge, maxdist, maxdistpos; 11 int fir[maxn], val[maxn]; 12 int fmaxm[maxn][maxmi], fminm[maxn][maxmi]; 13 struct Edge{ 14 int to, v, next; 15 }; 16 Edge edge[maxn]; 17 18 void addedge(int x, int y, int z){ 19 ++cntedge; 20 Edge &nowedge1=edge[cntedge]; 21 nowedge1.to=y, nowedge1.v=z, nowedge1.next=fir[x]; 22 fir[x]=cntedge; 23 ++cntedge; 24 Edge &nowedge2=edge[cntedge]; 25 nowedge2.to=x, nowedge2.v=z, nowedge2.next=fir[y]; 26 fir[y]=cntedge; 27 return; 28 } 29 30 void dfs(int now, int par, int dist){ 31 int nowedge, nowson; 32 nowedge=fir[now]; 33 while (nowedge){ 34 nowson=edge[nowedge].to; 35 if (nowson==par){ 36 nowedge=edge[nowedge].next; 37 continue; 38 } 39 dfs(nowson, now, dist+edge[nowedge].v); 40 nowedge=edge[nowedge].next; 41 } 42 if (dist>val[now]) val[now]=dist; 43 if (dist>maxdist){ 44 maxdist=dist; 45 maxdistpos=now; 46 } 47 return; 48 } 49 50 int flog2(float x) { 51 return ((unsigned&)x>>23&255)-127; 52 } 53 int dvalue(int head, int tail){ 54 int maxm=0, minm=1e9; 55 int lognum=flog2(tail-head+1); 56 maxm=max(fmaxm[head][lognum], fmaxm[tail-(1<<lognum)+1][lognum]); 57 minm=min(fminm[head][lognum], fminm[tail-(1<<lognum)+1][lognum]); 58 return maxm-minm; 59 } 60 61 void init(){ 62 memset(fir, 0, sizeof(fir)); 63 memset(val, 0, sizeof(val)); 64 for (int i=0; i<maxn; ++i){ 65 edge[i].next=edge[i].to=edge[i].v=0; 66 } 67 cntedge=0; 68 } 69 70 int ri(){ 71 char c; 72 int flag=1, r=0; 73 do{ 74 c=getchar(); 75 if (c=='-') flag=-1; 76 } while (!isgraph(c)); 77 do{ 78 r=r*10+c-48; 79 c=getchar(); 80 } while (isgraph(c)); 81 return r*flag; 82 } 83 84 int main(){ 85 int x, y, z; 86 while (~scanf("%d%d", &n, &m)){ 87 if (n==0&&m==0) break; 88 init(); 89 for (int i=1; i<n; ++i){ 90 x=ri(), y=ri(), z=ri(); 91 addedge(x, y, z); 92 } 93 int s=1, far1, far2; 94 maxdist=0, dfs(s, 0, 0); 95 far1=maxdistpos; 96 maxdist=0, dfs(far1, 0, 0); 97 far2=maxdistpos; 98 maxdist=0, dfs(far2, 0, 0); 99 //for (int i=1; i<=n; ++i) 100 //printf("%d\n", val[i]); 101 int q=0; 102 for (int i=1; i<=n; ++i) 103 fmaxm[i][0]=fminm[i][0]=val[i]; 104 for (int i=1; i<maxmi; ++i){ 105 for (int j=1; j<=n-(1<<i)+1; ++j){ 106 fmaxm[j][i]=max(fmaxm[j][i-1], fmaxm[j+(1<<(i-1))][i-1]); 107 fminm[j][i]=min(fminm[j][i-1], fminm[j+(1<<(i-1))][i-1]); 108 } 109 } 110 int h=1, t=1, maxm=0; 111 for (int i=0; i<m; ++i){ 112 q=ri(); 113 h=1, t=1, maxm=0; 114 while (t<=n){ 115 if (dvalue(h, t)<=q) ++t; 116 else ++h; 117 if ((t-h)>maxm) maxm=t-h; 118 } 119 printf("%d\n", maxm); 120 } 121 } 122 return 0; 123 }