感覺我直到前兩天才算是真正學會用樹狀陣列啊囧。。
有一類離線的區間詢問問題,可以有以下解法(我暫時會這麼多):離線+樹狀陣列||線段樹||莫隊演算法
線段樹先不說了,好久沒寫過了,而且本文的標題是樹狀陣列與莫隊囧。。
用樹狀陣列的關鍵在於,每次插入乙個點或者刪除乙個點要維護什麼東西,一般是插入右端點刪除左端點,維護的時候也要注意想清楚對哪部分答案有影響,刪除之後要及時處理。
而莫隊的不同就在於,離線的時候是分塊處理詢問的,然後每次只需要維護當前區間內的資訊,大多數情況下需要維護的東西都比樹狀陣列等少很多,因此想起來和寫起來都非常舒服,這種情況下增加乙個端點和刪除乙個端點要做的事情也不會很多。不過要注意的一點就是對於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...