21.5.31 t2
阿新 • • 發佈:2021-06-25
tag:可持久化線段樹,掃描線,雜湊
對於 \(40%\) 的暴力,不難想到直接暴力求出所有的列表,然後nth_element
考慮拓展這個做法,實際上如果用掃瞄線求出所有列表的話,變動只有 \(O(n)\) 次,於是想到可持久化陣列。注意要去重,所以再加個雜湊。
求答案的時候還是使用nth_element,不過要自定義cmp函式,這個可以兩個根一起線段樹上二分解決(可以用雜湊值判斷相同/空)
複雜度 \(O(nlogn)\)
update:單雜湊會被卡(即便是隨機資料)
#include<bits/stdc++.h> using namespace std; template<typename T> inline void Read(T &n){ char ch; bool flag=false; while(!isdigit(ch=getchar()))if(ch=='-')flag=true; for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48)); if(flag)n=-n; } enum{ MAXN = 100005, P1 = 1000000007, base1 = 20041107, P2 = 1000000009, base2 = 20050711 }; int n, k; int hs1[MAXN], hs2[MAXN]; struct node{ int lc, rc, val1, val2; #define lc(x) t[x].lc #define rc(x) t[x].rc #define val1(x) t[x].val1 #define val2(x) t[x].val2 }t[MAXN*100]; int node_cnt; void Update(int &x, int head, int tail, int loc){ if(head==tail){ if(val1(x)) x = ++node_cnt, val1(x) = val2(x) = 0; else x = ++node_cnt, val1(x) = hs1[head], val2(x) = hs2[head]; return; } int mid = head+tail >> 1; int tmpx = x; t[x=++node_cnt] = t[tmpx]; if(loc<=mid) Update(lc(x),head,mid,loc); if(mid<loc) Update(rc(x),mid+1,tail,loc); val1(x) = val1(lc(x))+val1(rc(x)); if(val1(x)>=P1) val1(x) -= P1; val2(x) = val2(lc(x))+val2(rc(x)); if(val2(x)>=P2) val2(x) -= P2; } int ans[MAXN], len; void print(int x, int head, int tail){ if(!x or !val1(x)) return; if(head==tail) return ans[++len] = head, void(); // if(head==tail) return printf("%d ",head), void(); int mid = head+tail >> 1; print(lc(x),head,mid); print(rc(x),mid+1,tail); } char check(int x, int y, int head, int tail, int rx, int ry){ if(head==tail) return (val1(x)!=0||val2(x)!=0)?ry!=0:!rx; int mid = head+tail >> 1; if(val1(lc(x))!=val1(lc(y))) return check(lc(x),lc(y),head,mid,rx||val1(rc(x))||val2(rc(x)),ry||val1(rc(y))||val2(rc(y))); return check(rc(x),rc(y),mid+1,tail,rx,ry); } inline bool cmp(const int &u, const int &v){return u==v?false:check(u,v,1,n,0,0);} typedef pair<int,int> pii; set<pii>st; struct upd{ int x, id; inline bool operator <(const upd &k)const{return x<k.x;} }q[MAXN<<1]; int qcnt; int rts[MAXN<<1], cnt; int main(){ // freopen("2.in","r",stdin); // freopen("2.out","w",stdout); Read(n); Read(k); hs1[0] = 1; for(register int i=1; i<=n; i++) hs1[i] = 1ll*hs1[i-1]*base1%P1; hs2[0] = 1; for(register int i=1; i<=n; i++) hs2[i] = 1ll*hs2[i-1]*base2%P2; for(register int i=1; i<=n; i++){ qcnt++; Read(q[qcnt].x); q[qcnt].id = i; qcnt++; Read(q[qcnt].x); q[qcnt].id = i; } sort(q+1,q+qcnt+1); int rt; for(register int l=1, r; l<=qcnt; l=r+1){ Update(rt,1,n,q[l].id); r=l; while(r<qcnt and q[r+1].x==q[r].x) r++, Update(rt,1,n,q[r].id); if(!st.count(pii(val1(rt),val2(rt)))) rts[++cnt] = rt, st.insert(pii(val1(rt),val2(rt))); } // sort(rts+1,rts+cnt,cmp); // for(register int i=1; i<cnt; i++) print(rts[i],1,n), puts(""); // return 0; nth_element(rts+1,rts+k,rts+cnt,cmp); print(rts[k],1,n); cout<<len<<'\n'; for(register int i=1; i<=len; i++) printf("%d ",ans[i]);puts(""); return 0; }