牛客 买礼物
题目链接:https://ac.nowcoder.com/acm/contest/9983/E
思路: 把问题转换成 求区间中的数的下一个与当前数相同的数的最小值,
即区间最小值如果 小于r的话 那么就证明当前区间至少有两个相同的数
用nxt[] 记录与当前数相同的下一个数的位置,last 为与当前数相同的上一个数的位置,然后线段树维护nxt 即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define pi pair<int,int> 7 #define fi first 8 #define sc second 9 #define pb push_back 10 struct ac 11 { 12 int l,r,v; 13 }; 14 ac tr[maxn*2]; 15 int a[maxn],pos[maxn]; 16 int nxt[maxn],last[maxn]; 17 18 void pushup(int x) 19 { 20 tr[x].v=min(tr[x<<1].v,tr[x<<1|1].v); 21 } 22 23 void build(int x,int l,int r) 24 { 25 tr[x]={l,r}; 26 if(l==r) 27 { 28 tr[x].v=nxt[l]; 29 } 30 else 31 { 32 int mid=(l+r)/2; 33 build(x<<1,l,mid); 34 build(x<<1|1,mid+1,r); 35 pushup(x); 36 } 37 } 38 39 void update(int x,int p,int v) 40 { 41 int L=tr[x].l,R=tr[x].r; 42 if(L==R) 43 { 44 tr[x].v=v; 45 } 46 else 47 { 48 int mid=(L+R)/2; 49 if(p<=mid) update(x<<1,p,v); 50 if(p>mid) update(x<<1|1,p,v); 51 pushup(x); 52 } 53 } 54 55 int query(int x,int l,int r) 56 { 57 int L=tr[x].l,R=tr[x].r; 58 if(l<=L&&R<=r) 59 { 60 return tr[x].v; 61 } 62 else 63 { 64 int mid=(L+R)/2; 65 int ans=1e9; 66 if(l<=mid) ans=query(x<<1,l,r); 67 if(r>mid) ans=min(ans,query(x<<1|1,l,r)); 68 return ans; 69 } 70 } 71 72 73 74 int main() 75 { 76 ios::sync_with_stdio(0); 77 cin.tie(0); 78 int n,q; 79 cin>>n>>q; 80 for(int i=1;i<=n;i++) cin>>a[i]; 81 for(int i=1;i<=n;i++) 82 { 83 last[i]=pos[a[i]]; 84 pos[a[i]]=i; 85 } 86 for(int i=1;i<=n;i++) pos[a[i]]=n+1; 87 for(int i=n;i>=1;i--) 88 { 89 nxt[i]=pos[a[i]]; 90 pos[a[i]]=i; 91 } 92 build(1,1,n); 93 while(q--) 94 { 95 int d; 96 cin>>d; 97 if(d==1) 98 { 99 int x; 100 cin>>x; 101 nxt[last[x]]=nxt[x]; 102 last[nxt[x]]=last[x]; 103 update(1,last[x],nxt[x]); 104 nxt[x]=n+1; 105 update(1,x,n+1); 106 } 107 else 108 { 109 int l,r; 110 cin>>l>>r; 111 if(query(1,l,r)>r) cout<<0<<'\n'; 112 else cout<<1<<'\n'; 113 } 114 } 115 116 117 118 119 }

浙公网安备 33010602011771号