一维数组数组形式
int c[N], maxn;
inline int Lowbit(int x){return x&(-x);}
void change(int i, int x)//i点增量为x
{
while(i <= maxn)
{
c[i] += x;
i += Lowbit(i);
}
}
int sum(int x){//区间求和 [1,x]
int ans = 0;
for(int i = x; i >= 1; i -= Lowbit(i))
ans += c[i];
return ans;
}
求区间最值:
struct Tree{
//手动初始化num数组
int lowbit(int x){ return x&(-x); }
int a[100005], num[100005], maxn;
void init(int len){
maxn = len;
for (int i = 1; i <= maxn; i++){
a[i] = num[i];
for (int j = 1; j < lowbit(i); j <<= 1)
a[i] = min(a[i], a[i - j]);
}
}
void updata(int pos, int val){
num[pos] = val;
for (int i = pos; i <= maxn; i += lowbit(i)){
a[i] = val;
for (int j = 1; j < lowbit(i); j <<= 1)
a[i] = min(a[i], a[i - j]);
}
return;
}
int query(int l, int r){
int ans = num[r];
while (true){
ans = min(ans, num[r]);
if (r == l) break;
for (r -= 1; r - l >= lowbit(r); r -= lowbit(r))
ans = min(ans, a[r]);
}
return ans;
}
}tree;
改段求段模版:
const int N = 4e5 + 100;
template<class T>
struct Tree{
T c[2][N];
int maxn;
void init(int x){
maxn = x+10; memset(c, 0, sizeof c);
}
inline int lowbit(int x){ return x&-x; }
T sum(T *b, int x){
T ans = 0;
if (x == 0)ans = b[0];
while (x)ans += b[x], x -= lowbit(x);
return ans;
}
void change(T *b, int x, T value){
if (x == 0)b[x] += value, x++;
while (x <= maxn)b[x] += value, x += lowbit(x);
}
T get_pre(int r){
return sum(c[0], r) * r + sum(c[1], r);
}
void add(int l, int r, T value){//区间加权
change(c[0], l, value);
change(c[0], r + 1, -value);
change(c[1], l, value * (-l + 1));
change(c[1], r + 1, value * r);
}
T get(int l, int r){//区间求和
return get_pre(r) - get_pre(l - 1);
}
};
Tree<ll> x, y;
逆向使用时:
int c[N], maxn;
inline int Lowbit(int x){return x&(-x);}
int sum(int i)//单点更新i点改为x
{
int ans = 0;
while(i <= maxn)
{
ans += c[i];
i += Lowbit(i);
}
return ans;
}
void change(int x, int value){//[1,x]增量为value
for(int i = x; i >= 1; i -= Lowbit(i))
c[i] += value;
}
树状数组求逆序数:
4 3 1 2
i = 1 : 插入4 : update(4,1),sum(4)返回1,那么当前比4大的为i - 1 = 0;
i = 2 : 插入3 : update(3,1),sum(3)返回1,那么当前比3大的为i - 1 = 1;
i = 3 : 插入1 : update(1,1),sum(1)返回1,那么当前比1大的为i - 1 = 2;
i = 4 : 插入2 : update(2,1),sum(2)返回2,那么当前比2大的为i - 2 = 2;
//逆序数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int N=1000005;
#define LL __int64
LL cal[N],res[N],ans,ros[N];
LL n,maxn,minm;
int lowbit(int x) {return x&-x;}
LL getsum(int x) {
LL s=0;
for(;x>0;s+=cal[x],x-=lowbit(x));
return s;
}
void update(int x,int value) {
for(;x<=maxn;cal[x]+=value,x+=lowbit(x));
}
int find(int value) {
int l=1,r=maxn,mid;
while(l<=r) {
mid=(l+r)>>1;
if(ros[mid]==value) return mid;
else if(ros[mid]>value) r=mid-1;
else l=mid+1;
}
return -1;
}
int main() {
int i,j,k;
LL total;
while(~scanf("%d",&n)) {
for(i=1;i<=n;i++) {
scanf("%I64d",&res[i]);
ros[i]=res[i];
}
memset(cal,0,sizeof(cal));
sort(ros+1,ros+n+1);
for(j=1,i=2;i<=n;i++) {
if(ros[i]!=ros[j]) ros[++j]=ros[i];
}
maxn=j;
for(i=1,total=0;i<=n;i++) {
k=find(res[i]);
update(k,1);
total+=i-getsum(k);
}
printf("%I64d\n",total);
}
return 0;
}
/*
3 3 1 2
ans=2
*/
二维树状数组支持对矩阵的子块操作,单点操作,子块求和
const int MAX=1200;
int c[MAX][MAX];
int n;
int LowBit(int t){ return t&(-t);}
int Sum(int endx,int endy)//求和 求矩阵[1,1]-[endx,endy]的和
{
int sum=0;
int temp=endy;
while(endx>0)
{
endy=temp;//
while (endy>0)
{
sum+=c[endx][endy];
endy-=LowBit(endy);
}
endx-=LowBit(endx);
}
return sum;
}
void add(int addx,int addy,int num)//在[x,y]位置上加上 num
{
int temp=addy;
while (addx <=n)
{
addy=temp;
while(addy<=n)
{
c[addx][addy]+=num;
addy+=LowBit(addy);
}
addx+=LowBit(addx);
}
}
int GetSum(int l,int b,int r,int t)//求[l,b]-[r,t]的和 若是点 则是GetSum(x,y,x,y)
{
return Sum(r,t)-Sum(r,b-1)-Sum(l-1,t)+Sum(l-1,b-1);
}
void updat(int x,int y,int val){ //更新[1,1]-[x,y]区间的点 都+val
for (;x<=n;x+=LowBit(x))
for (int i=y;i<=n;i+=LowBit(i))
c[x][i]+=val;
}
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
updat(x1, y1, 1);
updat(x2 + 1, y2 + 1, -1);
updat(x1, y2 + 1, -1);
updat(x2 + 1, y1, -1);