1. 程式人生 > 其它 >21.5.31 t2

21.5.31 t2

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;
}