专栏文章

树状数组

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mir1aqi5
此快照首次捕获于
2025/12/04 14:07
3 个月前
此快照最后确认于
2025/12/04 14:07
3 个月前
查看原文

树状数组-1

定点修改,区间查询

参考P3374
用前缀和来实现:
CPP
#include<bits/stdc++.h>
using namespace std;

const int N=200000000;
int n,m,tmp,x,y,k,op;
int a[N];
unsigned long long ans;

int lowbit(int x)
{
    return x&(-x);//取x的补码
}

void add(int x,int k)
{
    for(int i=x;i<=n;i+=lowbit(i))//把受影响的前缀和进行更改
    {
        a[i]+=k;
    }
}

int find(int l,int r)
{
    for(int i=r;i;i-=lowbit(i))//先加上所有前缀和
    {
        ans+=a[i];
    }
    for(int i=l-1;i;i-=lowbit(i))//减去前面多余的
    {
        ans-=a[i];
    }
    return 0;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        add(i,tmp);
    }
    for(int i=1;i<=m;i++)
    {
        cin>>op>>x;
        if(op==1)
        {
            cin>>k;
            add(x,k);
        }
        else
        {
            cin>>y;
            ans=0;
            find(x,y);
            cout<<ans<<endl;
        }
    }
    return 0;
}


区间修改,定点查询

参考P3368
用差分实现:
CPP
#include<bits/stdc++.h>
using namespace std;

int n,m,tmp,x,y,k,op,pre;
int a[500007],num[500007];
long long ans;

int lowbit(int x)
{
    return x&-x;
}

void add(int x,int k)
{
    for(int i=x;i<=n;i+=lowbit(i))//修改差分
    {
        a[i]+=k;
    }
}

void find(int r)
{
    for(int i=r;i>=1;i-=lowbit(i))
    {
        ans+=a[i];
	}   
    return ;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>num[i];
    }
    for(int i=1;i<=m;i++)
    {
        cin>>op;
        if(op==1)
        {
        	cin>>x>>y>>k; 
            add(x,k);
            add(y+1,-k);//修改后变化的是x,y+1
        }
        else
        {
            cin>>x;
            ans=0;
			find(x);
            cout<<num[x]+ans<<endl;
        }
    }
    return 0;
}


逆序对

CPP
#include<bits/stdc++.h>
using namespace std;

const int N=5e5+10;
int  n,m,tmp,x,y,k;
char op;
int a[N],t[N],d[N];

int lowbit(int x)
{
    return x&(-x);
}

bool cmp(int x,int y)
{
    if(a[x]==a[y])
    {
        return x>y;
    }
    return a[x]>a[y];
}

void add(int x)
{
    for(int i=x;i<=n;i+=lowbit(i))
    {
        t[i]++;
    }
}

int sum(int x)
{
    int res=0;
    for(int i=x;i;i-=lowbit(i))
    {
        res+=t[i];
    }
    return res;
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        d[i]=i;
    }
    sort(d+1,d+1+n,cmp);
    long long ans=0;
    for(int i=1;i<=n;i++)
    {
        add(d[i]);
        ans+=sum(d[i]-1);
    }
    cout<<ans<<endl;
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...