題解 掉進兔子洞
阿新 • • 發佈:2020-07-22
題目大意
給出\(n\)個數,\(m\)次查詢,查詢互相獨立,每次查詢給出三個區間\([l1,r1],[l2,r2],[l3,r3]\),求出三個區間一個一個刪去相同數字之後剩餘數的個數。
思路
好秒啊!!!
首先我們可以離散化,但是與普通離散化不同的是,這裡離散化的結果實際上是小於等於這個數的個數。顯然這樣並不會影響結果。至於為什麼下面解釋。
我們考慮如何求出在三個區間都出現的數的個數。誒?似乎可以\(\texttt{bitset}\)+莫隊?但是我們發現我們沒有辦法統計出現次數誒?但是其實我們統計一下需要修改的點\(p\)已經出現的次數為\(cnt\),把\(bitset_{p-cnt}\)
但是直接這樣做會爆空間,我們可以迴圈利用一下,查詢分成\(3\)次即可。
\(\texttt{Code}\)
#include <bits/stdc++.h> using namespace std; #define Int register int #define MAXN 100005 #define MAXM 34010 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;} template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);} template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} struct node{ int l,r,t; void Putin(int g){read (l,r),t = g;} }q[MAXM * 3]; bool cmp1 (node a,node b){return a.l < b.l;} bool cmp2 (node a,node b){return a.r < b.r;} map <int,int> mp; bitset <MAXN> nb,ans[MAXM]; int n,m,tot = 1,a[MAXN],cnt[MAXN],nans[MAXM]; void ins (int p){nb[p - cnt[p]] = 1,cnt[p] ++;} void del (int p){cnt[p] --,nb[p - cnt[p]] = 0;} void Solve (){ if (tot >= m) return ;int tp = 0,nl = 0,nr = 0; for (Int i = 1;i <= MAXM - 10 && tot <= m;++ tot,++ i){ ++ tp,q[tp].Putin(i),nans[i] += q[tp].r - q[tp].l + 1; ++ tp,q[tp].Putin(i),nans[i] += q[tp].r - q[tp].l + 1; ++ tp,q[tp].Putin(i),nans[i] += q[tp].r - q[tp].l + 1; } for (Int i = 1;3 * i <= tp;++ i) ans[i].set ();sort (q + 1,q + tp + 1,cmp1); for (Int i = 1;i <= tp;i += 320){ int r = min (i + 319,tp); sort (q + i,q + r + 1,cmp2); } for (Int i = 1;i <= tp;++ i){ if (nr < q[i].l){ for (Int j = nl;j <= nr;++ j) del (a[j]);nl = q[i].l,nr = q[i].r; for (Int j = nl;j <= nr;++ j) ins (a[j]); } else{ while (nl < q[i].l) del (a[nl ++]); while (nl > q[i].l) ins (a[-- nl]); while (nr < q[i].r) ins (a[++ nr]); while (nr > q[i].r) del (a[nr --]); } ans[q[i].t] &= nb; } for (Int i = nl;i <= nr;++ i) del (a[i]); for (Int i = 1;3 * i <= tp;++ i) write (nans[i] - (int)ans[i].count () * 3),putchar ('\n'),nans[i] = 0; } signed main(){ read (n,m); for (Int i = 1;i <= n;++ i) read (a[i]),mp[a[i]] ++;map <int,int>::iterator it,it1; for (it = mp.begin(),it1 = it,it1 ++;it1 != mp.end();++ it,++ it1) it1 -> second += it -> second; for (Int i = 1;i <= n;++ i) a[i] = mp[a[i]]; Solve (),Solve (),Solve (); return 0; } ```題解 掉進兔子洞