https://codeforces.com/problemset/problem/1000/F
感觉可以用莫队草过去但是我不会写常数小的莫队+值域分块
看看tle 莫队code
// Problem: F. One Occurrence
// Contest: Codeforces - Educational Codeforces Round 46 (Rated for Div. 2)
// URL: https://codeforces.com/problemset/problem/1000/F
// Memory Limit: 768 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=5e5+9;
const int M=5e5+1;
int a[N];
int t,tt;
int L[N],R[N],pos[N];
int LL[M],RR[M],PP[M];
int c[M],vis[M];
int ans[N];
struct Q{
int l,r,id;
friend bool operator < (const Q &a,const Q &b){
return pos[a.l]^pos[b.l]?pos[a.l]<pos[b.l]:pos[a.l]&1?a.r<b.r:a.r>b.r;
}
}que[N];
int query(){
int ans=0;
for(int i=1;i<=PP[M-1];i++){
if(vis[i]){
for(int j=LL[i];j<=RR[i];j++){
if(c[j]==1){
ans=j;
break;
}
}
}
}
return ans;
}
void modify(int pos,int val){
if(val==1){
if(c[pos]==1){
vis[PP[pos]]--;
}
if(c[pos]==0){
vis[PP[pos]]++;
}
}else{
if(c[pos]==1){
vis[PP[pos]]--;
}
if(c[pos]==2){
vis[PP[pos]]++;
}
}
c[pos]+=val;
}
void add(int pos){
modify(a[pos],1);
}
void del(int pos){
modify(a[pos],-1);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
t=sqrt(n);
for(int i=1;i<=t;i++){
L[i]=(i-1)*t+1;
R[i]=i*t;
}
if(R[t]<n){
t++;
L[t]=R[t-1]+1;
R[t]=n;
}
for(int i=1;i<=t;i++){
for(int j=L[i];j<=R[i];j++){
pos[j]=i;
}
}
tt=sqrt(M);
for(int i=1;i<=tt;i++){
LL[i]=(i-1)*tt+1;
RR[i]=i*tt;
}
if(RR[tt]<M){
tt++;
LL[tt]=RR[tt-1]+1;
RR[tt]=M;
}
for(int i=1;i<=tt;i++){
for(int j=LL[i];j<=RR[i];j++){
PP[j]=i;
}
}
int q;
cin>>q;
for(int i=1;i<=q;i++){
cin>>que[i].l>>que[i].r;
que[i].id=i;
}
sort(que+1,que+1+q);
int l=1,r=0;
for(int i=1;i<=q;i++){
while(que[i].l>l)del(l++);
while(que[i].l<l)add(--l);
while(que[i].r>r)add(++r);
while(que[i].r<r)del(r--);
ans[que[i].id]=query();
}
for(int i=1;i<=q;i++){
cout<<ans[i]<<'\n';
}
return 0;
}
接下来是ac的主席树
很像HH的项链,维护上一个相同的值的位置
我们维护上一个相同值的位置,维护区间最小值,如果最小值小于l,就有说明有[l,r]有一个值的数量是1
为了防止第一个出现的值影响答案,我们还要把第一个出现的值修改成INF(原本是0)
这样就可以在线操作完
因为每个数有可能修改2次,把N要再开大2倍
// Problem: F. One Occurrence
// Contest: Codeforces - Educational Codeforces Round 46 (Rated for Div. 2)
// URL: https://codeforces.com/problemset/problem/1000/F
// Memory Limit: 768 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
using namespace std;
const int N=5e5+9;
int a[N],vis[N],last[N];
//可持久化线段树
struct KCJSEG{
#define tl(id) seg[id].l
#define tr(id) seg[id].r
#define ll long long
#define INF 1e6
struct node{
int L,R;
int l,r;
int mn,index;
}seg[N<<6];
void pushup(node &id,node &l,node &r){
if(l.mn>r.mn){
id.mn=r.mn;
id.index=r.index;
}else{
id.mn=l.mn;
id.index=l.index;
}
}
void pushup(int id){pushup(seg[id],seg[tl(id)],seg[tr(id)]);}
int root[N],index,mx;
int inrange(int L,int R,int l,int r){return L>=l && R<=r;}
int outofrange(int L,int R,int l,int r){return L>r || l>R;}
void build(int &id,int l,int r){
id=++index;
seg[id]={l,r};
if(l==r){
seg[id].mn=INF;
seg[id].index=l;
return;
}
int mid=(l+r)>>1;
build(tl(id),l,mid);
build(tr(id),mid+1,r);
pushup(id);
}
void update(int post,int &curr,int l,int r,int pos,int v){
curr=++index;
seg[curr]=seg[post];
if(l==r){
seg[curr].mn=v;
return;
}
int mid=(l+r)>>1;
if(mid>=pos){
update(tl(post),tl(curr),l,mid,pos,v);
}else{
update(tr(post),tr(curr),mid+1,r,pos,v);
}
pushup(curr);
}
node query(int curr,int l,int r){
if((seg[curr].L>=l && seg[curr].R<=r)){
return seg[curr];
}else{
int mid=(seg[curr].L+seg[curr].R)>>1;
if(mid>=r){
return query(tl(curr),l,r);
}else if(mid<l){
return query(tr(curr),l,r);
}else{
node res;
node left=query(tl(curr),l,r);
node right=query(tr(curr),l,r);
pushup(res,left,right);
return res;
}
}
}
}t;
#define node KCJSEG::node
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>n;
t.build(t.root[0],1,n);
for(int i=1;i<=n;i++){
cin>>a[i];
t.root[i]=t.root[i-1];
if(vis[a[i]]){
t.update(t.root[i],t.root[i],1,n,vis[a[i]],INF);
last[a[i]]=vis[a[i]];
t.update(t.root[i],t.root[i],1,n,i,last[a[i]]);
vis[a[i]]=i;
}else{
vis[a[i]]=i;
t.update(t.root[i],t.root[i],1,n,i,0);
}
}
int q;
cin>>q;
for(int i=1;i<=q;i++){
int l,r;
cin>>l>>r;
node ans=t.query(t.root[r],l,r);
if(ans.mn>=l){
cout<<0<<'\n';
}else{
cout<<a[ans.index]<<'\n';
}
}
return 0;
}