One Occurrence [CodeForces1000F]
这个题目有多种写法
1.线段树动态更新与查找
pos[i]记录位置i上出现的数上次出现的位置。将询问按右区间排序。
从1到n扫,把线段树上pos[i]的值改成INF,
比如 1 1 ,线段树原来是 0 1 ,扫完第二个 1 后,线段树变成 INF 1,那么查找的时候,查找 L到 R之内最小的那个值,注意最后还要判断这个最小值是不是比L还要小。
code:
#include <bits/stdc++.h>
using namespace std;
#define File(x) freopen("(x)","r",stdin)
#define pf printf
#define ull unsigned long long
#define db double
#define ll long long
const int MAXN=5e5+10;
#define MAXM
#define P
int T, n, m, l, r, siz, lim, bol[MAXN], ans[MAXN], t[MAXN], a[MAXN],as;
struct Q {int l, r, x, y, id;} q[MAXN];
bool CMP(Q x, Q y)
{
return x.r<y.r;
}
int pos[MAXN],la[MAXN],lw[MAXN],pr[MAXN],mn[MAXN<<2],num[MAXN<<2];
void build(int u,int L,int R,int ps){
if(L==R){
mn[u]=pos[ps];
return;
}
int lson=u<<1,rson=u<<1|1,mid=L+R>>1;
if(ps<=mid)
build(lson,L,mid,ps);
else
build(rson,mid+1,R,ps);
mn[u]=min(mn[lson],mn[rson]);
}
void upd(int u,int L,int R,int ps){
if(L==R){
mn[u]=MAXN+10000;return;
}
int lson=u<<1,rson=u<<1|1,mid=L+R>>1;
if(ps<=mid)
upd(lson,L,mid,ps);
else
upd(rson,mid+1,R,ps);
mn[u]=min(mn[lson],mn[rson]);
}
int Q(int u,int L,int R,int l,int r){
int lson=u<<1,rson=u<<1|1,mid=L+R>>1;
int w1=0,w2=0;
if(mn[u]>=MAXN)return 0;
// cout<<"Q"<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
// cout<<mn[lson]<<"&"<<mn[rson]<<" "<<mn[u]<<endl;
if(L==R)return mn[u]<MAXN+1?a[L]:0;
if(mn[rson]<l&&r>mid)
if(w2=Q(rson,mid+1,R,l,r))return w2;
if(mn[lson]<l&&l<=mid){
if(w1=Q(lson,L,mid,l,r))return w1;
}
return 0;
}
int main()
{
cin>>n;
for(int i=0;i<(MAXN<<2);i++)mn[i]=MAXN+100000;
for(int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
}
for(int i=1; i<=n; ++i) {
pos[i]=la[a[i]];
la[a[i]]=i;
}
cin>>m;
for(int i=1; i<=m; ++i) {
scanf("%d%d", &q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1, q+m+1, CMP);
int ps=0;
for(int i=1; i<=m; ++i) {
while(ps<q[i].r){
++ps;
build(1,1,n,ps);
if(pos[ps]>0){
upd(1,1,n,pos[ps]);
}
}
ans[q[i].id]=Q(1,1,n,q[i].l,q[i].r);
}
for(int i=1; i<=m; ++i) printf("%d\n", ans[i]);
}
2.莫队
注意数据集合的增和删。用一个stack,增就直接入栈,删就把栈顶放到这个数原来的位置。(可以记录每个数在栈位置).注意这份代码会T。
T——T
#include <bits/stdc++.h>
using namespace std;
#define File(x) freopen("(x)","r",stdin)
#define pf printf
#define ull unsigned long long
#define db double
#define ll long long
const int MAXN=5e5+10;
#define MAXM
#define P
int T, n, m, l, r, siz, lim, bol[MAXN], ans[MAXN], t[MAXN], num[MAXN], a[MAXN],as;
struct Q {int l, r, x, y, id;} q[MAXN];
int stk[MAXN],top=0,pos[MAXN];
void add(int x, int k)
{
// cout<<x<<"-"<<k<<endl;
if(k==1)stk[++top]=x,pos[x]=top;
else{
pos[stk[top]]=pos[x];
stk[pos[x]]=stk[top];
--top;
}
}
bool CMP(Q x, Q y)
{
if(bol[x.l]==bol[y.l]) {
if(bol[x.l]&1) return x.r<y.r;
else return x.r>y.r;
}
return x.l<y.l;
}
int main()
{
cin>>n;
l=1, r=0, lim=0, siz=max(1, (int)sqrt(n));
for(int i=1; i<=5e5+5; ++i) num[i]=t[i]=0;
for(int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
bol[i]=(i-1)/siz+1;
}
cin>>m;
for(int i=1; i<=m; ++i) {
scanf("%d%d", &q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1, q+m+1, CMP);
for(int i=1; i<=m; ++i) {
while(r<q[i].r) {//jiaru
r++;
if(!num[a[r]]) add(a[r], 1);
else {
if(num[a[r]]==1)
add(a[r],-1);
}
num[a[r]]++;
}
while(r>q[i].r) {//tichu
num[a[r]]--;
if(num[a[r]]==1) add(a[r], 1);
else if(num[a[r]]==0)add(a[r],-1);
r--;
}
while(l<q[i].l) {//tichu
num[a[l]]--;
if(!num[a[l]]) add(a[l], -1);
if(num[a[l]]==1)add(a[l],1);
l++;
}
while(l>q[i].l) {//jiaru
l--;
if(!num[a[l]]) add(a[l], 1);
else if(num[a[l]]==1)add(a[l],-1);
num[a[l]]++;
}
ans[q[i].id]=stk[top];
}
for(int i=1; i<=m; ++i) printf("%d\n", ans[i]);
}