1. 程式人生 > >Codeforces Round #248 (Div. 2) B題 【資料結構:樹狀陣列】

Codeforces Round #248 (Div. 2) B題 【資料結構:樹狀陣列】

題目大意:給n(1 ≤ n ≤ 105)個數據(1 ≤ vi ≤ 109)其中有m(1 ≤ m ≤ 105)個問題,分兩種,第一種:給出l,r,讓你求出v[l],v[r]之間的所有資料和;第二種:先將原資料升序排序得到vv陣列,給出l,r,讓你求出vv[l],vv[r]之間的所有資料和;

此題如果用暴力求解,由於資料太大,會TLE,所以利用樹狀陣列,快速求解區間和的問題。

如果不懂樹狀陣列,可以去看看關於資料結構的知識

程式碼:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int v[100011];
int vv[100011];
long long Cv[100011];// 每個C陣列代表v[i-lowbit(i)+1]到v[i]之間的和
long long Cvv[100011];

int lowbit(int x)       
{
    return x&(x^(x-1));
}
long long Sumv(int i)   //求出陣列v[1]到v[i]的和
{
    long long result=0;
    while (i>=1)
    {
        result+=Cv[i];
        i-=lowbit(i);
    }
    return result;
}
long long Sumvv(int i)   //求出陣列vv[1]到vv[i]的和
{
    long long result=0;
    while (i>=1)
    {
        result+=Cvv[i];
        i-=lowbit(i);
    }
    return result;
}
int main()
{
    int n,m,t,l,r;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&v[i]);
        vv[i]=v[i];
    }
    sort(vv,vv+n+1);
    for(int i=1;i<=n;i++)
    {
        for(int j=i-lowbit(i)+1;j<=i;j++)
            Cv[i]+=v[j];
        for(int j=i-lowbit(i)+1;j<=i;j++)
            Cvv[i]+=vv[j];
    }
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&t,&l,&r);
        if(t==1)
        {
            printf("%I64d\n",Sumv(r)-Sumv(l-1));
        }
        else
        {
            printf("%I64d\n",Sumvv(r)-Sumvv(l-1));
        }
    }
    return 0;
}

此題也可以不用樹狀陣列,可以用s[i]陣列代表v[1]到v[i]的所有資料和,要求v[l]到v[r]之間的資料和,只需要用s[r]-s[l-1]就行了,兩種問題都一樣,大家可以自己試試。