樹狀陣列模板 逆序對

2022-08-31 15:15:18 字數 3373 閱讀 1927

顧名思義,lowbit這個函式的功能就是求某乙個數的二進位制表示中最低的一位1,舉個例子,x = 6,它的二進位制為110,那麼lowbit(x)就返回2,因為最後一位1表示2

求lowbit的兩種方法

int lowbit(x) 

int lowbit(x) 

c[i]代表 子樹的葉子結點的權值之和

c[1]=a[1];

c[2]=a[1]+a[2];

c[3]=a[3];

c[4]=a[1]+a[2]+a[3]+a[4];

c[5]=a[5];

c[6]=a[5]+a[6];

c[7]=a[7];

c[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];

對照式子可以發現c[i]=a[i-2^k+1]+a[i-2^k+2]+......a[i]; (k為i的二進位制中從最低位到高位連續零的長度)例如i=8時,k=3;

樹狀陣列的**

輸入 6

1 2 3 4 5 6

輸出15

1 3 3 10 5 11

#include#include #include #include#include#include using namespace std;

const int m=200000+10;

const int max=0x3f3f3f3f;

typedef long long ll;

ll a[101010],c[101010],t[101010],n;

int lowbit(ll x)

int getsum(ll i)//求前幾項和

return ans;

}void update(ll i,ll v)//更新

}int main()

ll ans=getsum(5);//為前幾項和

printf("%lld\n",ans);

for(i=1;i<=n;i++)

return 0;

}

若求前x到y項的和 getsum(y)-getsum(x-1)

首先看一下離散化

離散化,把無限空間中有限的個體對映到有限的空間中去,以此提高演算法的時空效率。

通俗的說,離散化是在不改變資料相對大小的條件下,對資料進行相應的縮小。例如:

原資料:1,999,100000,15;處理後:1,3,4,2;

原資料:,,;

處理後:,,;

舉個例子     輸入n=6    9 1 0 5 4 4  輸出 5 2 1 4 3

看離散化**  (有去重的作用)

#include#include #include #include#include#include using namespace std;

const int m=200000+10;

const int max=0x3f3f3f3f;

typedef long long ll;

ll a[101010],c[101010],t[101010];

int main()

在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序

求逆序對的**

輸入 5

9 1 0 5 4

輸出 6

#include#include #include #include#include#include using namespace std;

const int m=200000+10;

const int max=0x3f3f3f3f;

typedef long long ll;

ll a[101010],c[101010],t[101010],n;

int lowbit(ll x)

int getsum(ll i)//求前幾項和

return ans;

}void update(ll i,ll v)//更新

}int main()

sort(t+1,t+n+1);

m=unique(t+1,t+n+1)-t-1;

for(i=1; i<=n; i++)

a[i]=lower_bound(t+1,t+m+1,a[i])-t;

// for(int i=1;i<=m;i++)

// printf("%d\n",a[i]);

ll ans=0;

for(i=1;i<=n;i++)

printf("%lld\n",ans);

return 0;

}

區間a,b都加2 求區間x,y的和(區間修改 區間查詢模板)

#include#include #include #include#include#include using namespace std;

const int m=200000+10;

const int max=0x3f3f3f3f;

typedef long long ll;

ll a[101010],c[101010],t[101010],n=9;

ll aa[10000]=,bb[10000]=;

ll lowbit(ll x)

ll getsum(ll i,ll q)//求前幾項和

return ans;

}void update(ll i,ll v,ll q)//更新

}int main()

{ //a,b區間都加2 求x,y區間的和 視最初都為0 所以只是求增加的和

ll a,b,x,y,i,j,ans=0;

memset(aa,0,sizeof(aa));

memset(bb,0,sizeof(bb));

scanf("%lld%lld%lld%lld",&a,&b,&x,&y);

update(a,2,aa);

update(b+1,-2,aa);

update(a,a*2,bb);

update(b+1,-(b+1)*2,bb);

ans+=(y+1)*getsum(y,aa)-getsum(y,bb);

ans-=x*getsum((x-1),aa)

樹狀陣列求逆序對

題目描述 給定乙個陣列a,它包含n個整數,分別是a 1 a 2 a n 如果存在下標i和j,使得 i j 且 a i a j 同時成立,則 i,j 就為乙個 逆序對 那麼a陣列總共有多少對不同的 逆序對 輸入格式 1247.in 第一行為n 1 n 100000 接下來是n行,每行乙個長整型範圍內的...

樹狀陣列求逆序對

很久以前就學了樹狀陣列,也知道可以用來求逆序對,然而一直沒弄明白他是怎麼實現的 可能當時沒搞清楚逆序對是什麼吧。逆序對就是如果i j a i a j 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...

逆序對(樹狀陣列 歸併)

題目描述 貓貓tom和小老鼠jerry最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。最近,tom老貓查閱到乙個人類稱之為 逆序對 的東西,這東西是這樣定義的 對於給定的一段正整數序列,逆序對就是序列中i小於j同時ai大於aj的有序對。知道這概念後,他們...