Machine Learning(CF-940F)
Problem Description
You come home and fell some unpleasant smell. Where is it coming from?
You are given an array a. You have to answer the following queries:
You are given two integers l and r. Let ci be the number of occurrences of i in al:?r, where al:?r is the subarray of a from l-th element to r-th inclusive. Find the Mex of {c0,?c1,?...,?c109}
You are given two integers p to x. Change ap to x.
The Mex of a multiset of numbers is the smallest non-negative integer not in the set.
Note that in this problem all elements of a are positive, which means that c0 = 0 and 0 is never the answer for the query of the second type.
Input
The first line of input contains two integers n and q (1?≤?n,?q?≤?100?000) — the length of the array and the number of queries respectively.
The second line of input contains n integers — a1, a2, ..., an (1?≤?ai?≤?109).
Each of the next q lines describes a single query.
The first type of query is described by three integers ti?=?1, li, ri, where 1?≤?li?≤?ri?≤?n — the bounds of the subarray.
The second type of query is described by three integers ti?=?2, pi, xi, where 1?≤?pi?≤?n is the index of the element, which must be changed and 1?≤?xi?≤?109 is the new value.
Output
For each query of the first type output a single integer ?— the Mex of {c0, c1, ..., c109}.
Sample Input
10 4
1 2 3 1 1 2 2 2 9 9
1 1 1
1 2 8
2 7 1
1 2 8
Sample Output
2
3
2
題意:給出一個長度為 n 的數組以及 m 個詢問,對于每個詢問 q 有兩種操作,q 為 1 時查詢區間 [l,r] 中每個數字出現次數的 mex,q 為 2 時將位置 p 的值修改為 x,其中 mex 代表一些數字中最小的未出現的自然數
思路:帶修莫隊+離散化
這個題實際上是?數顏色(洛谷-P1903)?的變種,由于需要統計出現次數需要使用桶排,而數值最大達到 1E9,因此需要離散化,離散化后進行帶修莫隊即可,最后暴力求 mex
Source Program
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #define PI acos(-1.0) #define E 1e-9 #define INF 0x3f3f3f3f #define LL long long const int MOD=10007; const int N=200000+5; const int dx[]= {-1,1,0,0}; const int dy[]= {0,0,-1,1}; using namespace std;struct Node{int l,r;//詢問的左右端點int time;//時間維度int id;//詢問的編號 }q[N]; struct Change{int pos;//要修改的位置int col;//要改成的值 }c[N]; int n,m,a[N],temp[N]; int block;//分塊 int numQ,numC;//查詢、修改操作的次數 int cnt[N],sum[N]; int res[N];bool cmp(Node a,Node b){//排序return (a.l/block)^(b.l/block) ? a.l<b.l : ((a.r/block)^(b.r/block)?a.r<b.r:a.time<b.time); }void add(int x){//統計新的,根據具體情況修改sum[cnt[x]]--;cnt[x]++;sum[cnt[x]]++; } void del(int x){//減去舊的,根據具體情況修改sum[cnt[x]]--;cnt[x]--;sum[cnt[x]]++; } void change(int x,int ti){//改變時間軸if(c[ti].pos>=q[x].l&&c[ti].pos<=q[x].r){del(a[c[ti].pos]);//刪除指定位置上的值add(c[ti].col);//統計新的數}swap(c[ti].col,a[c[ti].pos]);//直接互換,下次執行時必定是回退這次操作 } int main(){while(scanf("%d%d",&n,&m)!=EOF){numQ=0;numC=0;memset(sum,0,sizeof(sum));memset(cnt,0,sizeof(cnt));block=pow(n,0.66666);//分塊int numTemp=0;for(int i=1;i<=n;++i){scanf("%d",&a[i]);temp[++numTemp]=a[i];}for(int i=1;i<=m;i++){int op;scanf("%d",&op);if(op==1){//查詢操作++numQ;//查詢操作次數+1scanf("%d%d",&q[numQ].l,&q[numQ].r);q[numQ].id=numQ;//序號q[numQ].time=numC;//時間軸}else{//修改操作++numC;//修改操作次數+1scanf("%d%d",&c[numC].pos,&c[numC].col);temp[++numTemp]=c[numC].col;}}//離散化sort(temp+1,temp+1+numTemp);numTemp=unique(temp+1,temp+1+numTemp)-temp;for(int i=1;i<=n;i++)a[i]=lower_bound(temp+1,temp+1+numTemp,a[i])-temp;for(int i=1;i<=numC;i++)c[i].col=lower_bound(temp+1,temp+1+numTemp,c[i].col)-temp;sort(q+1,q+numQ+1,cmp);//對詢問進行排序int l=1,r=0,time=0;//左右指針與時間軸for(int i=1;i<=numQ;i++){int ql=q[i].l,qr=q[i].r;//詢問的左右端點int qtime=q[i].time;//詢問的時間軸while(l>ql) add(a[--l]);//[l-1,r,time]while(l<ql) del(a[l++]);//[l+1,r,time]while(r<qr) add(a[++r]);//[l,r+1,time]while(r>qr) del(a[r--]);//[l,r-1,time]while(time<qtime) change(i,++time);//[l,r,time+1]while(time>qtime) change(i,time--);//[l,r,time-1]res[q[i].id]=1;while(sum[res[q[i].id]]>0)res[q[i].id]++;}for(int i=1;i<=numQ;i++)printf("%d\n",res[i]);}return 0; }?
總結
以上是生活随笔為你收集整理的Machine Learning(CF-940F)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++语言基础 —— 循环结构
- 下一篇: 合法整数集(51Nod-1315)