第一道帶修改的莫隊。學習ing傳送門:dynamic len(set(a[l:r]))
當然也可以訪問vjudge。 另類傳送門
題意:
有乙個序列,對於這個序列有兩種操作。
1、詢問[l, r]這個區間裡有多少個不同的數
2、修改某個位置的值。
如果沒寫過莫隊的修改,應該會能想到樹套樹(orz但是本人蒟蒻不會寫樹套樹啊)。但是有了莫隊之後情況就不一樣了。**量比樹套樹要少很多。
莫隊的修改:
分塊的時候要分成 2 / 3塊(沒證明過)。
時間複雜度為n5
3
分塊排序的時候,先按左端點的塊排序,再按右端點的塊排序。
最後按修改時間排序。
這裡的修改時間為,這個詢問操作前面出現過多少次修改操作。
對於每一次查詢,先將他退回或前進到修改的時間。
再進行分塊的查詢。有沒有一點時光倒流的感覺呢。
這裡要注意,以前寫莫隊每太在意l指標和r指標的交錯,這道題如果移動的時候交錯了就會wa。
所以,我們應該優先移動r指標向右,再移動l指標向左,剩下兩個隨意操作。
這要能保證這兩個指標不會錯位。就是不會出現r < l的情況
#include
#define maxn 1000005
using namespace std;
struct question qsn[maxn];
struct modify mod[maxn];
intpos[maxn];
int flag[maxn];
int a[maxn];
int lans[maxn];
intlast[maxn];
bool mark[maxn];
intq, ans, n, cnt;
int cmp(question a, question b)
if (pos[a.r] != pos[b.r])
return a.time
< b.time;
}void clear()
void add(int
x) flag[a[x]]++;
mark[x] = true;
}void del(int
x) mark[x] = false;
}void modify(int
x, int v) else
}void solve()
while (time > qsn[i].time)
while (r < qsn[i].r)
while (l > qsn[i].l)
while (r > qsn[i].r)
while (l < qsn[i].l)
lans[qsn[i].idx] = ans;
}for (int i = 1; i <= q; i++)
}int main()
clear();
for (int i = 1; i <= m; i++) else
}solve();
}}/*
7412
1321
4q 1
6m 3
2q 1
6q 3
5*/
樹上莫隊演算法
繼續回來寫部落格 記錄點有意思的題目什麼的。貌似寫過這個的沒多少人 所以我也記錄一點。首先序列上的莫隊大家都應該很熟悉了 那麼樹上的莫隊要怎麼搞呢?先來看個題目 spoj cot2 求樹上兩點間路徑上有多少個不同的點權。序列上的莫隊是把詢問按照左端點分塊了 可是樹上沒有左端點,怎麼辦呢?我們把樹分塊...
模板 莫隊演算法
題意 給定乙個大小為n的陣列,陣列中所有元素的大小 n。你需要回答m個查詢。每個查詢的形式是l,r,k。你需要回答在範圍 l,r 中至少重複k次的數字的個數。n,m 100000 誒,這題卡了好久,tle,中間棄了一段,然後今天學弟學莫隊,拿出這個題,他也沒什麼想法,然後我頓時退一步海闊天空了。最開...
模板 莫隊演算法
這個演算法是由之前的國家隊隊長莫濤巨神 orz 發明的,所以尊稱莫隊演算法。如果我們知道區間 l,r 就能在o 1 求出 l 1,r l 1,r l,r 1 l,r 1 的話,那就可以用莫隊演算法了。1 排序,以左段點所在的塊為第一關鍵字,以右端點為第二關鍵字 2 從左往右處理詢問 離線 3 不斷調...