例題:動態區間第k小
先上**:
#include#include#include
#include
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define n 50005
#define m 20005
using
namespace
std;
const
int inf=1000000007
;struct
zeroq[n+m],q1[n+m],q2[n+m];
int tree[n],tot=0
,n,m,ans[m];
int t,x,y,k,cnt=0
;int
input[n];
char
c;void add(int a,int k)
int ask(int a)
void solve(int ql,int qr,int l,int
r)
int t1=0,t2=0
;for(int i=ql;i<=qr;i++)
else
}for(int i=1;i<=t1;i++)if(q1[i].op)add(q1[i].id,-q1[i].op);
for(int i=1;i<=t1;i++)q[i+ql-1]=q1[i];
for(int i=1;i<=t2;i++)q[i+ql+t1-1]=q2[i];
solve(ql,t1+ql-1
,l,mid);
solve(t1+ql,qr,mid+1
,r);
}int
main()
for(int i=1;i<=m;i++)
else
}solve(1,tot,-inf,inf);
for(int i=1;i<=cnt;i++)printf("
%d\n
",ans[i]);
}}
解釋一下struct zero:
對於修改函式:x表示修改的值,op表示該操作是修改還是查尋,id為該操作作用點在陣列中的位置
對於查尋函式:x,y表示查尋區間,k表示在這區間中查詢第k小,op和id意義同上
整體二分的主要思路就是把一段操作(修改和查尋)序列分成兩段,分治操作
solve(ql,t1+ql-1,l,mid);
solve(t1+ql,qr,mid+1,r);
就是這樣
那麼怎麼分段呢
我們來看solve(ql,qr,l,r)函式,
這裡ql,qr,l,r的意義就是序列中ql到qr的所有詢問,它的答案在l到r之間
算了我在**裡講吧,那麼請繼續看**
void solve(int ql,int qr,int l,intr)
int t1=0,t2=0;
for(int i=ql;i<=qr;i++)
else
}for(int i=1;i<=t1;i++)if(q1[i].op)add(q1[i].id,-q1[i].op);//重置樹狀陣列
for(int i=1;i<=t1;i++)q[i+ql-1]=q1[i];
for(int i=1;i<=t2;i++)q[i+ql+t1-1]=q2[i];
solve(ql,t1+ql-1
,l,mid);
solve(t1+ql,qr,mid+1
,r);//分治
}
然後注意main裡把乙個點變成x的操作要拆成兩個操作實現
if(c=='c')
整體二分專題
何謂整體二分?一般的二分只適用於單個詢問的,如果有很多個詢問,就變成了n 2n 2 n2或更高但整體二分則可以迅速處理多個詢問的問題 首先需要離線,讀入所有詢問 然後我們二分答案,這時候我們將詢問分成兩個部分,如果l r就直接更新答案,否則考慮分治,詢問的答案在左邊的丟到左邊,答案在右邊的則丟到右邊...
學習 整體二分
在?看看整體二分 整體二分是個啥,就是遞迴進行二分答案的操作,按照當前二分出的區間對詢問操作和修改操作進行左右分類。有點類似於歸併排序的樣子,但是需要用個維護區間的資料結構來維護當前詢問區間的區間的查詢和修改操作,每次查詢完當前區間的操作之後,需要清空之前的修改操作。整體二分可以保證會互相影響的操作...
整體二分總結
通常與 cdq 分治同類談論,處理的問題性質本質上有不同 整體二分,顯然整體 同時 處理多個二分查詢,通常帶有修改,我們需要分治處理 solve l,r,l,r 為操作 l,r 中答案均在 l,r 區間內 我們是分治處理 l,mid 操作的前 n 個為新增操作 靜態陣列 掃一遍操作,新增操作時把 v...