【CodeForces 940F】 Machine Learning
|字数总计:1.2k|阅读时长:5分钟|阅读量:|
题目传送门
这道题不算特别难,基本算得上是带修莫队的板子题,首先应该想到的是统计每个数字出现的次数,不过这道题比较有趣的一点是,要求查询的是每个数字出现次数的 Mex,所以还应该统计一个出现次数的出现次数,具体来说,我们用一个 cnt 数组来统计数字出现次数,然后再用一个 cnt2 数组来统计 cnt 数组内每个数字的出现次数,在更新 cnt 的时候顺便也更新一下 cnt2 就可以了。
但有一点不太好想的是如何求这个出现次数的 Mex,一开始,我想的是可以跟着 cnt2 数组一起更新,但这样会有很多问题,因为我们无法判断如果 cnt2ans 不为 0 了,那么答案应该是多少,所以我采用了一个很玄学的方法,用一个 bitset 来统计哪些出现次数是没有出现过的,最后找一个最小的就可以了,这样我们只需要在更新 cnt2 的时候判断一下这个被更新的值是否从 0 到 1 或是从 1 到 0,然后相对应地把 bitset 也更新一下就好了。而在找的时候,可以用 bitset 的一个成员函数_Find_first
,它的作用是寻找这个 bitset 中第一个 1,并且返回它的位置,也就是所有数字出现次数的 Mex。
对了,这道题由于值域为 [1,109],所以需要离散化,在离散化时要注意,不仅对于 a 数组要离散化,对于修改操作中要求改成的那些数也要进行离散化,而且应该是一起进行,否则有可能会 RE,同时,由于这两部分是一起离散化的,所以最终离散后的值域应该是 [1,2×n],记得要把数组大小开够,否则也会 RE。
参考代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| #include<bits/stdc++.h> #define N 200010 using namespace std; int n,m,p,len,k,k1,lastc,l=1,r,t,ans[N],cnt[N],cnt1[N],a[N]; struct Query { int x; int y; int z; int id; bool operator < (Query const &a) const { return ((x/len)^(a.x/len)) ? x/len<a.x/len : ((y/len)^(a.y/len)) ? y/len<a.y/len : z<a.z; } }; struct Change { int p; int v; }; Query q[N]; Change c[N]; vector<int> rec; bitset<N> num; void add(int i) { cnt1[cnt[a[i]]]--; if(!cnt1[cnt[a[i]]]) num[cnt[a[i]]]=1; cnt[a[i]]++; if(!cnt1[cnt[a[i]]]) num[cnt[a[i]]]=0; cnt1[cnt[a[i]]]++; } void del(int i) { cnt1[cnt[a[i]]]--; if(!cnt1[cnt[a[i]]]) num[cnt[a[i]]]=1; cnt[a[i]]--; if(!cnt1[cnt[a[i]]]) num[cnt[a[i]]]=0; cnt1[cnt[a[i]]]++; } int main() { scanf("%d%d",&n,&m); len=(int)pow(n,2.0/3.0); rec.push_back(0); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); rec.push_back(a[i]); } for(int i=1;i<=m;i++) { int op,l,r; scanf("%d%d%d",&op,&l,&r); if(op==1) q[++k]=Query{l,r,lastc,k}; else { k1++; lastc=k1; rec.push_back(r); c[k1]=Change{l,r}; } } sort(rec.begin(),rec.end()); rec.erase(unique(rec.begin(),rec.end()),rec.end()); for(int i=1;i<=n;i++) a[i]=lower_bound(rec.begin(),rec.end(),a[i])-rec.begin(); for(int i=1;i<=k1;i++) c[i].v=lower_bound(rec.begin(),rec.end(),c[i].v)-rec.begin(); sort(q+1,q+1+k); cnt1[0]=0x3f3f3f3f; num.set(); num[0]=0; for(int i=1;i<=k;i++) { while(l>q[i].x) add(--l); while(r<q[i].y) add(++r); while(l<q[i].x) del(l++); while(r>q[i].y) del(r--); while(t<q[i].z) { t++; if(l<=c[t].p&&r>=c[t].p) { del(c[t].p); swap(a[c[t].p],c[t].v); add(c[t].p); } else swap(a[c[t].p],c[t].v); } while(t>q[i].z) { if(l<=c[t].p&&r>=c[t].p) { del(c[t].p); swap(a[c[t].p],c[t].v); add(c[t].p); } else swap(a[c[t].p],c[t].v); t--; } ans[q[i].id]=num._Find_first(); } for(int i=1;i<=k;i++) printf("%d\n",ans[i]); return 0; }
|