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

二维树状数组

时间:2024-11-25 11:56:18浏览次数:6  
标签:typedef 树状 int rep y1 二维 数组 fwt query

更新日志

思路

和一维没有多大区别。

插入时,双重循环,分别循环两个维度。查询时同理。

细节

如果查询区间和用二维前缀和的方法即可。

模板

struct fenwick{
    ll dat[N][N];
    int lowbit(int x){return x&-x;}
    void add(int x,int y,ll v){
        for(int i=x;i<=n;i+=lowbit(i)){
            for(int j=y;j<=n;j+=lowbit(j)){
                dat[i][j]+=v;
            }
        }
    }
    ll query(int x,int y){
        ll res=0;
        for(int i=x;i>0;i-=lowbit(i)){
            for(int j=y;j>0;j-=lowbit(j)){
                res+=dat[i][j];
            }
        }
        return res;
    }
}fwt;

ll getsum(int x1,int y1,int x2,int y2){
    return fwt.query(x2,y2)-fwt.query(x2,y1-1)-fwt.query(x1-1,y2)+fwt.query(x1-1,y1-1);
}

例题

矩阵乘法

代码

前注:非题解,不做详细讲解

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

typedef long long ll;
typedef unsigned long long ull;
typedef __int128 i128;
typedef double db;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
typedef pair<pii,pii> ppp;
template <typename Type>
using vec=vector<Type>;
template <typename Type>
using grheap=priority_queue<Type>;
template <typename Type>
using lrheap=priority_queue<Type,vector<Type>,greater<Type> >;
#define fir first
#define sec second
#define pub push_back
#define pob pop_back
#define puf push_front
#define pof pop_front
#define chmax(a,b) a=max(a,b)
#define chmin(a,b) a=min(a,b)
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define per(i,x,y) for(int i=y;i>=x;i--)

const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7/*998244353*/;

const int N=505,M=500*500+5,Q=6e4+5;

int n,q,m;
int a[N][N],x[M];
struct query{
    int x1,y1,x2,y2;
    int k;
}qs[Q];
int arr[Q],tmp[Q],ans[Q];
vec<pii> plcs[M];
bool can[M];

struct fenwick{
    int dat[N][N];
    int lowbit(int x){return x&-x;}
    void add(int x,int y,ll v){
        for(int i=x;i<=n;i+=lowbit(i)){
            for(int j=y;j<=n;j+=lowbit(j)){
                dat[i][j]+=v;
            }
        }
    }
    int query(int x,int y){
        int res=0;
        for(int i=x;i>0;i-=lowbit(i)){
            for(int j=y;j>0;j-=lowbit(j)){
                res+=dat[i][j];
            }
        }
        return res;
    }
}fwt;

int getsum(int x1,int y1,int x2,int y2){
    return fwt.query(x2,y2)-fwt.query(x2,y1-1)-fwt.query(x1-1,y2)+fwt.query(x1-1,y1-1);
}

void solve(int x,int y,int l,int r){
    if(l>r)return;
    if(l==r){
        rep(i,x,y)ans[arr[i]]=l;
        return;
    }
    int mid=l+r>>1;
    rep(i,l,mid){
        for(auto j:plcs[i]){
            fwt.add(j.fir,j.sec,1);
        }
    }
    int cnt=0;
    rep(i,x,y){
        query &now=qs[arr[i]];
        int sum=getsum(now.x1,now.y1,now.x2,now.y2);
        if(sum>=now.k){
            can[i]=true;
            cnt++;
        }else{
            can[i]=false;
            now.k-=sum;
        }
    }
    rep(i,l,mid){
        for(auto j:plcs[i]){
            fwt.add(j.fir,j.sec,-1);
        }
    }
    int cnt1=0,cnt2=0;
    rep(i,x,y){
        if(can[i]){
            tmp[x+cnt1]=arr[i];
            cnt1++;
        }else{
            tmp[x+cnt+cnt2]=arr[i];
            cnt2++;
        }
    }
    rep(i,x,y)arr[i]=tmp[i];
    solve(x,x+cnt-1,l,mid);
    solve(x+cnt,y,mid+1,r);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>q;
    rep(i,1,n)rep(j,1,n){
        cin>>a[i][j];
        x[++m]=a[i][j];
    }
    sort(x+1,x+1+m);
    m=unique(x+1,x+1+m)-x-1;
    rep(i,1,n)rep(j,1,n){
        a[i][j]=lower_bound(x+1,x+1+m,a[i][j])-x;
        plcs[a[i][j]].pub({i,j});
    }
    rep(i,1,q)cin>>qs[i].x1>>qs[i].y1>>qs[i].x2>>qs[i].y2>>qs[i].k;
    rep(i,1,q)arr[i]=i;
    solve(1,q,1,m);
    rep(i,1,q)cout<<x[ans[i]]<<"\n";
    return 0;
}

标签:typedef,树状,int,rep,y1,二维,数组,fwt,query
From: https://www.cnblogs.com/HarlemBlog/p/18567270

相关文章

  • Java数组与集合
    数组(array)概念:同一种类型数据的集合。其实数组就是一个容器。  定义格式1:  元素类型[]数组名=new元素类型\[元素个数或数组长度\];  示例:int[]arr=newint[x];  **定义格式2**:  元素类型[]数组名=new元素类型\[\]{元素,元素,......};  int[]a......
  • 多维数组与特殊矩阵:存储与压缩
    多维数组与特殊矩阵:存储与压缩一、多维数组的存储(一)基本概念多维数组是线性表的推广,例如二维数组可以看作是元素为一维数组的线性表,三维数组可以看作是元素为二维数组的线性表,以此类推。在内存中,多维数组需要按照一定的顺序进行存储,常见的存储方式有行优先存储和列优先存......
  • 425 周赛第一题 3364. 最小正和子数组
       给你一个整数数组 nums 和 两个 整数 l 和 r。你的任务是找到一个长度在 l 和 r 之间(包含)且和大于0的 子数组 的 最小 和。返回满足条件的子数组的 最小 和。如果不存在这样的子数组,则返回-1。子数组 是数组中的一个连续 非空 元素序列。 示......
  • 鸿蒙NEXT开发案例:二维码的生成与识别
    【引言】在本篇文章中,我们将探讨如何在鸿蒙NEXT平台上实现二维码的生成与识别功能。通过使用ArkUI组件库和相关的媒体库,我们将创建一个简单的应用程序,用户可以生成二维码并扫描识别。【环境准备】•操作系统:Windows10•开发工具:DevEcoStudioNEXTBeta1BuildVersion:5......
  • 分别写出数组的交集、并集、差集、补集这四个方法
    /***Calculatestheintersectionoftwoarrays.**@param{Array}arr1Thefirstarray.*@param{Array}arr2Thesecondarray.*@returns{Array}Anewarraycontainingtheelementspresentinbothinputarrays.*/functionintersection(arr1,arr......
  • 写个方法随机打乱一个数组
    functionshuffleArray(array){//创建数组的副本,避免修改原始数组constshuffledArray=[...array];//Fisher-Yates洗牌算法for(leti=shuffledArray.length-1;i>0;i--){constj=Math.floor(Math.random()*(i+1));//随机索引0到i......
  • 关于C语言 字符串(字符数组)s
    关于charC语言中的字符型用关键字char表示,它实际存储的是ASC码。字符常量可以用单引号法表示。在语法上可以把字符当做int型使用。字符串的实际长度每次存储字符串,应多分配字符个数加1,因为C语言的字符串被读取后会添加空字符"\0"结尾例如:存储"2357"到chara[20]中,a会存储......
  • Java学习笔记--对象数组,方法参数,命令行参数,快速生成方法
    目录一,对象数组Personp=newPerson();二,方法参数1.基本数据类型做方法参数传递2.引用数据类型做方法参数传递三,命令行参数四,快速生成方法1.快速生成方法2.快速将一段代码抽取到一个方法中 一,对象数组Person[]arr=newPerson[3];Personp=newPerson();......
  • 【一维数组】排名(rank)
    题目描述小X很关心自己在学校的表现。班主任手上有一本“个人得分记录本”,如果一位同学表现好就会加分,表现差则会扣分。学期结束,每位同学都得知了自己的个人得分。小X想知道其他同学情况如何,但由于排名不公布,他只好一个个去问班里的其他同学。现在,小X手上有班里共 N ......
  • [数组双指针] 0015. 三数之和
    文章目录1.题目链接2.题目大意3.示例4.解题思路5.参考代码1.题目链接15.三数之和-力扣(LeetCode)2.题目大意描述:给定一个整数数组nums。要求:判断nums中是否存在三个元素a、b、c,满足a+b+c==0。要求找出所有满足要求的不重复的三元组。说明:3≤n......