无修改树上查询数据结构

 

 

 

 

 以区间和查询为例,树代码如下所示

#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;
}

 

posted @ 2021-01-30 01:00  声声醉如兰  阅读(58)  评论(0编辑  收藏  举报