2021年牛客寒假集訓營第三場 E.買禮物(連結串列+線段樹(或主席樹))
阿新 • • 發佈:2021-02-07
主席樹做法待補
使用連結串列儲存同種禮物所在的位置
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");
}
}
}