5 5 1 2 3 2 3 4 4 5 3 3 4 2 1 2 3 4 5 0 0
1 3 3 3 5
RMQ:ST算法(Sparse Table):它是一种动态规划的方法。
以最小值为例。a为所寻找的数组.
用一个二维数组f(i,j)记录区间[i,i+2^j-1](持续2^j个)区间中的最小值。其中f[i,0] = a[i];
所以,对于任意的一组(i,j),f(i,j) = min{f(i,j-1),f(i+2^(j-1),j-1)}来使用动态规划计算出来。
这个算法的高明之处不是在于这个动态规划的建立,而是它的查询:它的查询效率是O(1).
假设我们要求区间[m,n]中a的最小值,找到一个数k使得2^k<n-m+1.
这样,可以把这个区间分成两个部分:[m,m+2^k-1]和[n-2^k+1,n].我们发现,这两个区间是已经初始化好的.
前面的区间是f(m,k),后面的区间是f(n-2^k+1,k).
这样,只要看这两个区间的最小值,就可以知道整个区间的最小值!
不过要注意这题需要扩栈。。。。。不然会超时。。。。。
#pragma comment (linker,"/STACK:102400000,102400000")
#pragma comment (linker,"/STACK:102400000,102400000") #include <iostream> #include <stdio.h> #include <stdlib.h> #include<string.h> #include<algorithm> #include<math.h> #include<queue> using namespace std; typedef long long ll; const int N=50010; int len,st,ed; int m,n; int maxd[N][2],lg[N],f[N][20],g[N][20],val[N]; int head[N]; int ip; struct edgenode { int to; int w; int next; } tu[100005]; void add(int u,int v,int w) { tu[ip].to=v,tu[ip].w=w,tu[ip].next=head[u],head[u]=ip++; } void dfs(int now,int pre,int sum) { if(sum>len)len=sum,st=now; for(int k=head[now]; k!=-1; k=tu[k].next) { int to=tu[k].to; if(to!=pre) dfs(to,now,sum+tu[k].w); } } void ddfs(int now,int pre,int sum,int num) { maxd[now][num]=sum; for(int k=head[now]; k!=-1; k=tu[k].next) { int to=tu[k].to; if(to!=pre) ddfs(to,now,sum+tu[k].w,num); } } void init_rmq() // 预处理 O(n*log(n)) { int i,j; for(i=1; i<=n; i++) { f[i][0]=g[i][0]=val[i]; } for(j=1; (1<<j)<=n; j++) { for(i=1; i+j-1<=n; i++) { if((i+(1<<(j-1))<=n)) { f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); //避免越界 g[i][j]=min(g[i][j-1],g[i+(1<<(j-1))][j-1]); } else { f[i][j]=f[i][j-1]; g[i][j]=g[i][j-1]; } } } } int query_rmq(int l,int r) { int k=lg[r-l+1]; return max(f[l][k],f[r-(1<<k)+1][k])-min(g[l][k],g[r-(1<<k)+1][k]); } int main() { lg[1]=0; for(int i=2; i<=50000; i++) lg[i]=lg[i>>1]+1; while(~scanf("%d%d",&n,&m)&&m+n) { ip=0; memset(head,-1,sizeof(head)); for(int i=0; i<n-1; i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } len=0; dfs(1,0,0); ed=st; len=0; dfs(st,0,0); ddfs(st,0,0,0); ddfs(ed,0,0,1); for(int i=1; i<=n; i++) val[i]=max(maxd[i][0],maxd[i][1]); init_rmq(); int res,id,ans; while(m--) { int q; scanf("%d",&q); ans=id=1; for(int i=1; i<=n; i++) { while(id<=i) { res=query_rmq(id,i); if(res>q) id++; else break ; } ans=max(ans,i-id+1); } printf("%d\n",ans); } } return 0; }