• 数据结构-树状数组


    一、前言

    感觉时间有点不太够了(整日摸鱼= =),打算简单内容就不说了模板直接丢在这里,多记一些应用方面的东西qwq

    二、模板

    #define Lof(i,a,b) for(Re int i=(a),_=(b);i<=_;i+=i&-i)
    #define Lor(i,a) for(Re int i=(a);i;i-=i&-i)
    struct BIT{//一维
    	int da[N];
    	void clear() {Ms(da,0);}
    	void Modify(int x,int d) {Lof(i,x,n)da[x]+=d;}
    	int query(int x) {int t=0;Lor(i,x)t+=da[x];return t;}
    }T;
    
    struct TDBIT{//二维
    	int da[N][N][N];
    	void clear() {Ms(da,0);}
    	void Modify(int p,int x,int y,int d) { Lof(i,x,n) Lof(j,y,m) da[p][i][j]+=d;}
    	int qry(int p,int x,int y) {int t=0;Lor(i,x) Lor(j,y) t+=da[p][i][j];return t;}
    	int query(int p,int x1,int y1,int x2,int y2) {return qry(p,x2,y2)+qry(p,x1-1,y1-1)-qry(p,x1-1,y2)-qry(p,x2,y1-1);}
    }T;
    

    三、应用

    树状数组的应用多种多样,这里持续总结吧~

    3.1 区间修改与求和

    现有原数组a[],b[]为a[]的标记差分数组(初始是0,只记录修改变化)。区间[l,r]都+x即为b[l]+=x,b[r+1]-=c。

    区间[l,r]求和即为sum(1,r)-sum(1,l),即只需求前缀和。

    修改后第i项的值为(a[i]+sum_{j=1}^ib[j]) ,那么(sum(1,r)=sum_{i=1}^r(a[i]+b[i]*(r-i+1)))

    化简后为(sum(1,r)=sum_{i=1}^ra[i]+(r+1)sum_{i=1}^rb[i]-sum_{i=1}^r(b[i]*i)) 第一项直接前缀和,后两项用树状数组维护即可

    另外和这个方法类似可推导出二维情况的式子,但需要维护4个二维树状数组= =

    3.2nlogn求逆序对

    将原数列离散化后一个一个插入统计和当前数逆序的数字有多少。

    3.3求LIS

    就维护小于等于i的长度最大值= =

    PS:想不到了(阿巴阿巴0.0),就先写到这吧遇上题再补充~

    本文版权归作者所有,未经允许不得转载。
  • 相关阅读:
    java泛型
    java集合
    java面向对象
    java常用类
    二分查找
    递归
    选择排序+冒泡排序
    threejs入门简单例子
    css表格合并边框以及单元格宽度计算方式
    Spring Boot 有哪些优点?
  • 原文地址:https://www.cnblogs.com/zuiyumeng/p/13585463.html
Copyright © 2020-2023  润新知