CF 940F - Machine Learning ( 带 修 )
题目: 链接:https://codeforces.com/problemset/problem/940/F
题意:给你n个数,a[i]有q个操作,操作有两种:操作1. 1 x y 表示询问, mex{ c[ 1 ],c[ x + 1 ],...c[ 1e9 ] } 的值, 其中 c[i] 表示 a[ i ] 在 区间 [ x , y ] 出现的次数, (mex{ } 的意思呢,是从1开始数,第一个不出现在集合 { } 里的数, 比如 mex{ 1, 2, 4 } = = 3 因为此题是从1开始数 ) 操作2. 2 p x 将 a[ p ] 重新赋值 为 x 对每个操作1 输出答案
思路: 将 a[ i ] 离散化 因为 数据有点大,然后找答案 直接 暴力 找 其他的基本上就是 带修莫队 的 模板了
#include<bits/stdc++.h> #define LL long long #define ULL unsigned long long #define rep(i,j,k) for(int i=j;i<=k;i++) #define dep(i,j,k) for(int i=k;i>=j;i--) #define INF 0x3f3f3f3f #define mem(i,j) memset(i,0,sizeof(i)) #define make(i,j) make_pair(i,j) using namespace std; const int N=2e5+5; int a[N],pos[N],num[N],cnt[N],now[N],p,ans[N],l=1,r=0; /// num就是a[i]在l,r出现的次数,然后cnt就是那个 mex { } 的集合 struct noq { int l,r,id,t; }q[N]; struct noc { int x,old,ne; }c[N]; map<int,int>vis; ///离散化 a[i] 需要 bool cmp(noq a,noq b) { if(pos[a.l]==pos[b.l]) { if(pos[a.r]==pos[b.r]) return a.t<b.t; return pos[a.r]<pos[b.r]; } return pos[a.l]<pos[b.l]; } int get(int x) { /// 得到 离散化后的a[i] if(vis[x]==0) vis[x]=++p; return vis[x]; } void add(int x,int d) { cnt[num[x]]--; num[x]+=d; cnt[num[x]]++; } void go(int x,int ne) { if(l<=x && x<=r) { add(a[x],-1); add(ne,1); } a[x]=ne; } int cal() {///找答案 for(int i=1;;i++) if(cnt[i]==0) return i; } int main() { int n,m; int head=0,tail=0; scanf("%d %d",&n,&m); int M=(int)pow(n,0.666666); rep(i,1,n) { scanf("%d",&a[i]); now[i]=a[i]=get(a[i]); pos[i]=(i-1)/M; } rep(i,1,m) { int ch; int x,y; scanf("%d %d %d",&ch,&x,&y); if(ch==1) q[++head]=(noq){x,y,head,tail}; else { y=get(y); ///记得y也要离散化,因为 now[x] 是 离散化后的 a[i] c[++tail]=(noc){x,now[x],y}; now[x]=y; } } sort(q+1,q+1+head,cmp); int t=0; rep(i,1,head) { while(t<q[i].t) go(c[t+1].x,c[t+1].ne),++t; while(t>q[i].t) go(c[t].x,c[t].old),--t; while(l<q[i].l) add(a[l++],-1); while(l>q[i].l) add(a[--l],1); while(r<q[i].r) add(a[++r],1); while(r>q[i].r) add(a[r--],-1); ans[q[i].id]=cal(); } rep(i,1,head) printf("%d\n",ans[i]); return 0; }
一步一步,永不停息