无修改树上查询数据结构
以区间和查询为例,树代码如下所示
#include <stdio.h> #include <algorithm> using namespace std; const int N=100010; int n,len,l,m; int lg[N<<2],a[N],pos[N]; int prel[21][N],prer[21][N]; int read() { int x=0,w=1; char ch; ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*w; } int max(int a,int b) { return a>b?a:b; } void build(int l,int r,int k,int d) //left,right,结点编号,树深度 { if(l==r) { pos[l]=k; return; } int mid=(l+r)>>1; prel[d][mid] = a[mid]; for(int i=mid-1; i>=l; i--) prel[d][i] = prel[d][i+1] + a[i]; prer[d][mid+1] = a[mid]+1; for(int i=mid+2; i<=r; i++) prer[d][i] = prer[d][i-1] + a[i]; build(l,mid,k<<1,d+1); build(mid+1,r,k<<1|1,d+1); return; } int query(int x,int y) { if(x==y) return a[x]; int d=lg[pos[x]]-lg[pos[x]^pos[y]]; return prel[d][x] + prer[d][y]; } int main() { int x,y; scanf("%d",&n); for(int i=1; i<=n; i++) a[i]=read(); for(len=2; len<n; len<<=1); l=len<<1; for(int i=2; i<=l; i++) lg[i]=lg[i>>1]+1; build(1,len,1,1); m=read(); while(m--) { x=read(); y=read(); printf("%d\n",query(x,y)); } return 0; }