首页 > 其他分享 >树状数组

树状数组

时间:2023-07-20 15:01:42浏览次数:30  
标签:return 树状 int lowbit cin add 数组 op

//树状数组
//利用lowbit函数将区间划分为以二进制结尾的长度的小区间,然后利用这些小区间相加,减少时间复杂度

//树状数组的本质就是前缀和+可修改区间,求单点前缀和,如果是求某一的区间和,需要稍加修改,下面有类似例题,维护前缀和还有i*前缀和就可以
//也就是说树状数组就是更快一点的前缀和,但是比前缀和的功能要多,可维护的种类更广泛

//楼兰图腾
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
string s;
int n,t,a[N],f[N],res,num,ans,m,g[N],low[N],tr[N];
bool vis[N];
int lowbit(int x){
    return x&-x;
}
void add(int x,int c)
{
    for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
int sum(int x)
{
    int op=0;
    for(int i=x;i>=1;i-=lowbit(i)) op+=tr[i];
    return op;
}
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++){
        int y=a[i];
        g[i]=sum(n)-sum(y);
        low[i]=sum(y-1);
        add(y,1);        
    }
    memset(tr,0,sizeof tr);
    for(int i=n;i>=1;i--){
        int y=a[i];
        ans+=g[i]*(sum(n)-sum(y));
        num+=low[i]*(sum(y-1));
        add(y,1);
    }
    cout<<ans<<" "<<num<<endl;
    return 0;
}

//一个简单的整数问题
//区间加数,求单点值
//利用树状数组与差分
//用树状数组维护差分
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
string s;
int n,t,a[N],f[N],res,num,ans,m,tr[N];
bool vis[N];
int lowbit(int x){
    return x&-x;
}
void add(int x,int c)
{
    for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
int sum(int x)
{
    int op=0;
    for(int i=x;i>=1;i-=lowbit(i)) op+=tr[i];
    return op;
}
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) add(i,a[i]-a[i-1]);
    while(m--){
        char s;
        int x,y,z;
        cin>>s;
        if(s=='C'){
            cin>>x>>y>>z;
            add(x,z),add(y+1,-z);
        }
        else if(s=='Q'){
            cin>>x;
            cout<<sum(x)<<endl;
        }
    }
    return 0;
}

//一个简单的整数问题2
//区间加+区间和
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
string s;
int n,t,a[N],f[N],res,num,ans,m,tr1[N],tr2[N];
bool vis[N];
int lowbit(int x){
    return x&-x;
}
void add(int tr[],int x,int c)
{
    for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
int sum(int tr[],int x)
{
    int op=0;
    for(int i=x;i>=1;i-=lowbit(i)) op+=tr[i];
    return op;
}
int pre_sum(int x){
    return sum(tr1,x)*(x+1)-sum(tr2,x);
}
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++){
        int y=a[i]-a[i-1];
        add(tr1,i,y),add(tr2,i,i*y);
    }
    while(m--){
        char op;
        int l,r,d;
        cin>>op>>l>>r;
        if(op=='Q') cout<<pre_sum(r)-pre_sum(l-1)<<endl;
        else{
            cin>>d;
            add(tr1,l,d),add(tr1,r+1,-d);
            add(tr2,l,d*l),add(tr2,r+1,-d*(r+1));
        } 
    }
    return 0;
}

//谜一样的牛
//从后向前找,假设现在的值是2,也就是从前到现在这个区间里面,这个牛的位置是第3小的牛
//如果有5头,x=2,也就是说有两头牛比他低,它就是第三小,也就是5-3=2,第2
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
string s;
int n,t,a[N],f[N],res,num,ans,m,tr[N];
bool vis[N];
int lowbit(int x){
    return x&-x;
}
void add(int x,int c){
    for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
int sum(int x){
    int op=0;
    for(int i=x;i>=1;i-=lowbit(i)) op+=tr[i];
    return op;
}
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) add(i,1);
    for(int i=n;i>=1;i--){
        int y=a[i]+1;
        int l=0,r=n;
        while(l<r){
            int mid=l+r>>1;
            if(sum(mid)>=y) r=mid;
            else l=mid+1;
        }
        f[i]=r;
        add(r,-1);
    }
    for(int i=1;i<=n;i++) cout<<f[i]<<" ";
    return 0;
}

 

标签:return,树状,int,lowbit,cin,add,数组,op
From: https://www.cnblogs.com/o-Sakurajimamai-o/p/17568434.html

相关文章

  • 代码随想录训练营 Day01- 数组(上)
    概述第一天主要学习的是数组相关的内容,相关学习的内容包括数组的基本特性的学习,二分搜索方法的学习。数组特点数组的基本特点包括:下标从0开始内存连续性(Java中定义数组需要直接声明其空间大小)数组元素不可以删,只能覆盖ArrayList底层是数组实现,其实际上应该叫一......
  • 初学C语言day04--数组
    一、数组什么是数组:变量的组合,是一种批量定义相同类型变量的方式    定义:类型名数组名[数量];intarr[5];注意:数组的长度一旦确定,无法改变使用:数组名[下标];下标:从0开始,范围:0~数量-1    遍历:把数组的数据从头到尾显示或访问一般与for循环配合,把循环变量i当做......
  • python 初始化结构体数组
    Python初始化结构体数组介绍在Python中,没有内置的结构体类型,但是我们可以通过类来模拟结构体的功能。结构体数组是一种常见的数据结构,用于存储多个相同类型的数据。在本文中,我将向你介绍如何在Python中初始化结构体数组。流程下面是初始化结构体数组的基本流程:步骤描述......
  • 合并有序数组
    合并有序数组方法1-递归//运用的思想就是比较谁大,谁就先被排进数组publicstaticvoidmerge(int[]a1,inti,intiEnd,intj,intjEnd,int[]a2,intk){//定义了一个a1数组,分了i,iEnd边界和j.jEnd边界,实际上是分成两个数组进行判......
  • 暑假集训随笔2 主席树/二维树状数组
    P4514上帝造题的七分钟题意维护对二维平面上的矩形区域各元素进行加法以及对矩形区域求和链接:https://www.luogu.com.cn/problem/P4514思路通过二维树状数组维护的二维前缀和利用差分实现矩形区域的区间加法与区间求和。具体而言,二维的前缀和可以仿照一维的前缀和进行定义......
  • shell脚本中对数组的操作汇总
    方法用例备注创建数组arr=(val_1val_2val_3)数组间的元素以空格分割。创建空数组arr_new=()访问数组arr=(val_1val_2val_3)echo"${arr[0]}"数组的索引从“0”开始,在这个例子中,脚本会输出“val_1”。访问数组的长度arr=(val_1val_2val_3)e......
  • 怎么遍历Java中可变数组
    如何遍历Java中的可变数组在Java中,可变数组是一种动态大小的数组,也称为动态数组或ArrayList。它可以根据需要自动调整大小,因此非常方便。遍历可变数组是经常使用的操作之一,本文将介绍如何遍历Java中的可变数组,并提供相应的代码示例。问题描述假设我们有一个可变数组,包含了一组学......
  • 一维数组之冒泡排序
    从b站上黑马程序员的C++课里学到的冒泡排序 1#include<iostream>2usingnamespacestd;3intmain()4{5intarr[6]={2,4,1,6,7,3};6for(inti=0;i<6;i++)//数组遍历7{8cout<<arr[i]<<"";9}1......
  • 数组
    一、数组1、数组的定义1)数组是相同类型数据的有序集合2)数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成3)每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问 2、数组的声明创建1)必须先声明数组变量,才能在程序中使用数组。声明数组变量的语......
  • 【Javascript】数组扩展方法:根据key重新分组
    1//数组扩展:根据key重新分组2//field:按什么字段分组3Array.prototype.GroupByKey=function(field)4{5varoriginalArr=this6lettempArr=[]7letresultData=[]8for(leti=0;i<originalArr.length;i++)9{10......