處理區間問題之樹狀陣列與莫隊演算法

2021-07-04 16:08:23 字數 2804 閱讀 4144

感覺我直到前兩天才算是真正學會用樹狀陣列啊囧。。

有一類離線的區間詢問問題,可以有以下解法(我暫時會這麼多):離線+樹狀陣列||線段樹||莫隊演算法

線段樹先不說了,好久沒寫過了,而且本文的標題是樹狀陣列與莫隊囧。。

用樹狀陣列的關鍵在於,每次插入乙個點或者刪除乙個點要維護什麼東西,一般是插入右端點刪除左端點,維護的時候也要注意想清楚對哪部分答案有影響,刪除之後要及時處理。

而莫隊的不同就在於,離線的時候是分塊處理詢問的,然後每次只需要維護當前區間內的資訊,大多數情況下需要維護的東西都比樹狀陣列等少很多,因此想起來和寫起來都非常舒服,這種情況下增加乙個端點和刪除乙個端點要做的事情也不會很多。不過要注意的一點就是對於10w級別的資料,這裡的增加和刪除操作必須是o(1)才不會超時。

還是隨便貼一下**吧:

hdu4358

莫隊

#include#include#include#include#include#include#include#include#pragma comment(linker, "/stack:1024000000,1024000000")

#include#include#include#include#includeusing namespace std;

typedef long long ll;

typedef unsigned long long ull;

#define rep(i,k,n) for(int i=(k);i<=(n);i++)

#define red(i,k,n) for(int i=(k);i>=(n);i--)

#define sqr(x) ((x)*(x))

#define clr(x,y) memset((x),(y),sizeof(x))

#define mod 1000000007

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)>(b)?(b):(a))

const int maxn = 100010;

int aa[maxn],a[maxn],l[maxn],r[maxn],p[maxn];

int n,k,m,dfn,cnt;

struct q

}r[u]=dfn;

}bool cmp(int x,int y)

dis();

rep(i,1,n-1)

dfn=0;

clr(vis,0);

dfs(1);

scanf("%d",&m);

rep(i,1,m)

sort(q+1,q+1+m);

clr(p,0);

int ll=1,rr=0;

cnt=0;

rep(i,1,m)

int sum(int k)

}b;mapmp,l,r;

vectore[maxn];

bool vis[maxn];

void dfs(int u)

}r[u]=dfn;

}int main()

mp.clear();

rep(i,1,n-1)

dfn=0;

clr(vis,0);

dfs(1);

scanf("%d",&m);

rep(i,1,m)

sort(q+1,q+1+m);

int t=1;

l.clear();

r.clear();

clr(nxt,0);

rep(i,1,n)

else

if(mp[a[i]]==k)

else if(mp[a[i]]>k)

r[a[i]]=i;

while(t<=m&&i==q[t].r)

if(t>m)break;

}printf("case #%d:\n",ii);

rep(i,1,m)printf("%d\n",ans[i]);

if(ii

用莫隊的話很多題都變成水題了。。。

#include#include#include#include#include#include#include#include#pragma comment(linker, "/stack:1024000000,1024000000")

#include#include#include#include#includeusing namespace std;

typedef long long ll;

typedef unsigned long long ull;

#define rep(i,k,n) for(int i=(k);i<=(n);i++)

#define red(i,k,n) for(int i=(k);i>=(n);i--)

#define sqr(x) ((x)*(x))

#define clr(x,y) memset((x),(y),sizeof(x))

#define mod 1000000007

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)>(b)?(b):(a))

const int maxn = 100010;

int n,m,a[maxn],ku,cnt;

bool in[maxn];

struct q

while(lq[i].l)

ans[q[i].id]=cnt;

}rep(i,1,m)printf("%d\n",ans[i]);

}return 0;

}

樹狀陣列之區間最值

數學原理 利用上面的性質,在樹狀陣列的尾部插入資料,來建立乙個樹狀陣列 void push int pos void update int pos,int v int pre c pos pos lowbit pos 父親的位置 更新父親 while pos n 沒有更新父親 else break ...

區間修改,查詢之樹狀陣列

方法 單點修改,單點查詢 這個沒什麼好說的,就是單純的陣列 單點修改,區間查詢 樹狀陣列 樹狀陣列能單點修改,並且區間1 n的和,區間查詢只需要用到字首和的思想就可以了。線段樹 區間修改,單點查詢 差分 區間修改只需改變兩個值,單點查詢時求一遍字首和。樹狀陣列 差分 在進行修改的時候匯入的數是差分的...

樹狀陣列區間求和與區間最值

樹狀陣列區間求和 修改的時間複雜度為o logn 查詢的時間複雜度為o logn lowbit函式這個函式的功能就是求某乙個數的二進位制表示中最低的一位1。舉個例子,x 6,它的二進位制為110,那麼lowbit x 就返回2,因為最後一位1表示2。而樹狀陣列的求和與下標的二進位制有關,詳情見圖 a...