1. 程式人生 > 其它 >2021年牛客寒假集訓營第三場 E.買禮物(連結串列+線段樹(或主席樹))

2021年牛客寒假集訓營第三場 E.買禮物(連結串列+線段樹(或主席樹))

技術標籤:資料結構牛客練習

傳送門

主席樹做法待補

使用連結串列儲存同種禮物所在的位置

n x t [ i ] nxt[i] nxt[i]表示下一個最近的和 a i a_i ai相同禮物的位置

l a s t [ i ] last[i] last[i]表示上一個最近的和 a i a_i ai相同禮物的位置

然後在修改時動態維護連結串列

線段樹維護 n x t [ ] nxt[] nxt[]的區間最小值

於是 [ l , r ] [l,r] [l,r]內查詢 n x t nxt nxt的最小值看是否小於等於 r r r就好了

#include <bits/stdc++.h>
using namespace std; #define mid (l+r>>1) #define ls (rt<<1) #define rs (rt<<1|1) #define lson ls,l,mid #define rson rs,mid+1,r const int maxn = 1e6+10; const int inf = 1e9+7; int n,q,nxt[maxn],last[maxn],pos[maxn],w[maxn<<2],a[maxn]; void build(int rt,int l,int r) { if( l==
r ){ w[rt] = nxt[l]; return; } build(lson); build(rson); w[rt] = min( w[ls],w[rs] ); } void update(int rt,int l,int r,int index,int val) { if( l>index||r<index ) return; if( l==r&&l==index ){ w[rt] = val; return; } update(lson,index,val); update(rson,index,val); w[rt] = min( w[ls]
,w[rs] ); } int ask(int rt,int l,int r,int L,int R) { if( l>R||r<L ) return inf; if( l>=L&&r<=R ) return w[rt]; return min( ask(lson,L,R),ask(rson,L,R) ); } signed main() { cin >> n >> q; for(int i=1;i<=n;i++) { scanf("%d",&a[i] ); if( pos[a[i]] ) last[i] = pos[a[i]], nxt[pos[a[i]]] = i; pos[a[i]] = i; } for(int i=1;i<=n;i++) if( nxt[i]==0 ) nxt[i] = n+1; build(1,1,n); for(int i=1;i<=n;i++) { int type,l,r; scanf("%d%d",&type,&l ); if( type==1 ) { nxt[last[l]] = nxt[l]; last[nxt[l]] = last[l]; update(1,1,n,last[l],nxt[l] ); update(1,1,n,l,n+1 ); nxt[l] = n+1, last[l] = 0; } else { scanf("%d",&r); if( ask(1,1,n,l,r)<=r ) puts("1"); else puts("0"); } } }