題意:給出乙個長度為\(n\)的排列\(p(p_1,p_2,...p_n)\),以及\(m\)個詢問。每次詢問某個區間\([l,r]\)中,最長的值域
連續段長度(例如)。\(n,m\leq 5\times 10^4\)
題解:
(這題網上有挺多做法的,莫隊+線段樹/莫隊+並查集/莫隊+棧/kd-tree,這裡我原本是想找kd-tree的題才找到這題的,但是沒想到怎麼做,用莫隊做完去查了題解發現還需要一些前置知識,考慮到自己的學習進度好幾天沒往下推了,暫時還是不推支線了x,其他做法就先欠著吧x,kd樹碰一碰就繼續推主線去)
就想著先把題做出來再說…於是其實就能很自然地想到用莫隊來處理詢問,很自然地去考慮一邊處理區間一邊維護乙個值域序列\(t\),\(t[i]\)表示\(i\)這個數是否在區間內,接著要求的「最長值域連續長度」就成了序列上最長連續的1的長度,很經典的線段樹的題:每個結點除了答案以外維護乙個左端點開始的最長連續1和右端點開始的最長連續1,接著類似分治那樣來維護(具體見**的update)
這樣一來每次修改的代價都是\(o(\log n)\),莫隊處理詢問自帶乙個根號,最終複雜度是\(o(n\sqrt n \log n)\)的。
const int n=5e4+5;
const int m=240;
struct queryq[n];
int n,m,t,bl[n],ans[n],a[n];
int tr[n<<2],ls[n<<2],rs[n<<2];
#define lson (node<<1)
#define rson (node<<1|1)
void update(int node,int l,int r)
if(rs[rson]==r-mid)
}void modify(int node,int l,int r,int x,int v)
int mid=(l+r)>>1;
if(mid>=x)modify(lson,l,mid,x,v);
else modify(rson,mid+1,r,x,v);
update(node,l,r);
}#undef lson
#undef rson
bool cmp1(query p,query q)
while(rqr)
ans[q[i].idx]=tr[1];
} rep(i,1,m)printf("%d\n",ans[i]);
return 0;
}
bzoj4358 permu 回滾莫隊
序列上的問題?想到莫隊。然而這題像bzoj4241 歷史研究一樣毒瘤,資瓷o 1 o 1 o 1 加入,不資瓷o 1 o 1 o 1 刪除。安利一波題解 bzoj4241 歷史研究qwq 所以像4241一樣,需要用到回滾莫隊。這裡開兩個陣列l,r l,rl,r,l i l i l i 表示加入i時,...
hdu 4358 莫隊演算法 dfs序列
解題思路 用dfs求出整棵樹的dfs序列,這樣以u為根節點的子樹就轉化到相對應的區間上了。由於是區間不修改查詢問題,這個時候就可以用莫隊演算法了。pragma comment linker,stack 16777216 include include include include includeu...
bzoj3585 莫隊 分塊
description 有乙個長度為n的陣列。m次詢問,每次詢問乙個區間內最小沒有出現過的自然數。input 第一行n,m。第二行為n個數。從第三行開始,每行乙個詢問l,r。output 一行乙個數,表示每個詢問的答案。sample input 5 52 1 0 2 1 3 32 3 2 41 2 ...