F. Machine Learning (带修改莫队)

https://codeforces.com/contest/940/problem/F

题意  给出n个数字,q个询问;

每次询问有两种类型,一种是询问区间,一种是单体修改;

询问区间是询问区间内最小的没用到的大于0的整数;

比如我有一串数字是 1 1 2 2 2 3    那么有两个1 三个2,一个3   出现次数分别有 两 三 一,  那么次数最小的没在区间内出现的是4;

对于这道题,除带修改莫队的模板之外,我们多加两个数组 vis cnt

vis数组用来记录某个数出现的频率,cnt用来记录出现过的频率

那么每次询问的答案便是最小的没出现过的频率

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=2e5+10;
  4 struct Query{
  5     int l,r,Tim,ID;  //左右端点,时间戳,询问区间的序号
  6 }q[maxn];
  7 struct Change{
  8     int pos,New,Old;  //记录改变位置,改变前的值(颜色),改变后的值(颜色)
  9 }c[maxn];
 10 int s[maxn];  //记录在计算区间答案时,这一时刻的每个位置为何数(颜色)
 11 int now[maxn];  //记录在目前的时间戳下,区间上各个数的值(颜色);
 12 int ans[maxn];  //用来记录答案
 13 int l=1,r=0;  //将一开始的询问区间定为L=1,r=0;
 14 int block;
 15 int Hash;
 16 int cnt[maxn];
 17 int vis[maxn];
 18 map<int,int>mp;
 19 int get(int x)
 20 {
 21     if(!mp[x]) mp[x]=++Hash;
 22     return mp[x];
 23 }
 24 bool cmp(Query a,Query b)
 25 {
 26     if(a.l/block!=b.l/block) return a.l<b.l;
 27     if(a.r/block!=b.r/block) return a.r<b.r;
 28     return a.Tim<b.Tim;
 29 }
 30 void revise(int x,int d)
 31 {
 32     cnt[vis[x]]--;
 33     vis[x]+=d;
 34     cnt[vis[x]]++;
 35 }
 36 void going(int x,int d)
 37 {
 38     if(l<=x&&x<=r){  //如果改变的位置在目前的区间内
 39         revise(d,1);  //则将改变后的数(颜色)更新
 40         revise(s[x],-1);  //将此位置之前的数(颜色)-1;
 41     }
 42     s[x]=d; //把这个位置的权值改变
 43 }
 44 int cal()
 45 {
 46    // printf("hahaha\n");
 47     int base=1;
 48     while(cnt[base]){
 49         base++;
 50     }
 51     return base;
 52 }
 53 int main()
 54 {
 55     int n,m;
 56     scanf("%d%d",&n,&m);
 57     block=pow(n,2.0/3);  //分块,普通莫队是直接开根号;
 58                         //待修改莫队是n的3分之2次方
 59                         //至于为什么,便是数据测试出这样分块算起来比较快
 60                         //很抱歉本人不会算此复杂度
 61     for(int i=1;i<=n;i++){
 62         scanf("%d",&s[i]);
 63         now[i]=s[i]=get(s[i]);
 64     }
 65     //从这里还是跑询问区间;将询问操作放进sort排序;
 66     int Time=0,num=0;
 67     while(m--){
 68         int sign; int x,y;
 69         scanf("%d%d%d",&sign,&x,&y);
 70         //x为左端点,y为右端点,Time是时间戳,num表示第几个询问
 71         if(sign==1) q[++num]=(Query){x,y,Time,num};
 72         //x为修改位置,y为修改后的值,now[x]为修改前的值
 73         //最后再将目前此位置的值该为y;
 74         else{
 75             y=get(y);
 76             c[++Time]=(Change){x,y,now[x]},now[x]=y;
 77         }
 78     }
 79    // printf("111111111111111111111111\n");
 80     sort(q+1,q+num+1,cmp);
 81   //  printf("xxixiixixix\n");
 82     int T=0;l=1,r=0;    //初始化
 83     for(int i=1;i<=num;i++){
 84        // printf("hahahahhahaahha\n");
 85         //时间戳发生改变,则时间前移后移代码
 86         while(T<q[i].Tim) going(c[T+1].pos,c[T+1].New),T++;
 87         while(T>q[i].Tim) going(c[T].pos,c[T].Old),T--;
 88         //区间发生改变,左右端点移动操作
 89         while(l<q[i].l) revise(s[l],-1),l++;
 90         while(l>q[i].l) revise(s[l-1],1),l--;
 91         while(r<q[i].r) revise(s[r+1],1),r++;
 92         while(r>q[i].r) revise(s[r],-1),r--;
 93         //将答案记录下来
 94        // printf("111111111\n");
 95         ans[q[i].ID]=cal();
 96     }
 97     for(int i=1;i<=num;i++)
 98         printf("%d\n",ans[i]);
 99     return 0;
100 }

原文地址:https://www.cnblogs.com/pangbi/p/12397618.html

时间: 2024-08-02 15:39:37

F. Machine Learning (带修改莫队)的相关文章

CF940F Machine Learning (带修改莫队)

题目链接 https://codeforces.com/contest/940/problem/F 题意 给出n个数字,q个询问: 每次询问有两种类型,一种是询问区间,一种是单体修改: 定义Ci为区间里数字 i 出现的次数,求Ci数组的mex #include<bits/stdc++.h> using namespace std; const int maxx = 2e5+10; struct qnode { int l,r,t,id; }e[maxx]; struct cnode { int

[UOJ #58][WC2013]糖果公园(树上带修改莫队)

Description Solution 树上带修改莫队…!VFK的题解写得很清楚啦 (我的程序为什么跑得这么慢…交的时候总有一种自己在卡测评的感觉…) #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define MAXN 100005 typedef long l

[BZOJ 4129]Haruna’s Breakfast(树上带修改莫队)

Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵 树上,每个结点都有一样食材,Shimakaze要考验一下她. 每个食材都有一个美味度,Shimakaze会进行两种操作: 1.修改某个结点的食材的美味度. 2.对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少.即mex值. 请你帮帮Haruna吧. Solution 树上带修改莫队 统计答案的时候也分块查询,找到第一个没满的块开始一个一个找 #include<i

【Luogu】P1903数颜色(带修改莫队)

题目链接 带修改莫队模板. 加一个变量记录现在是第几次修改,看看当前枚举的询问是第几次修改,改少了就改过去,改多了就改回来. 话说我栈用成队列了能过样例?!!!! 从此深信一句话:样例是出题人精心设计的,绞尽脑汁才设计出一个能让错误代码通过的数据qwqqqqq #include<cstdio> #include<cstdlib> #include<cctype> #include<algorithm> #include<cstring> #inc

BZOJ.2453.维护队列([模板]带修改莫队)

题目链接 带修改莫队: 普通莫队的扩展,依旧从[l,r,t]怎么转移到[l+1,r,t],[l,r+1,t],[l,r,t+1]去考虑 对于当前所在的区间维护一个vis[l~r]=1,在修改值时根据是否在当前区间内修改即可. 块大小取\(O(n^{\frac{2}{3}})\),排序依次按左端点所在块.右端点所在块.修改次数(时间) 复杂度为\(O(n^{\frac{5}{3}})\) (证明在这) #include <cmath> #include <cstdio> #inclu

BZOJ2120数颜色(带修改莫队)

2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 7384  Solved: 2998[Submit][Status][Discuss] Description 墨 墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col.为了满足墨墨的要求,你知道你需要

[bzoj2453]维护队列_带修改莫队

维护队列 bzoj-2453 题目大意:给定一个n个数序列,支持查询区间数的种类数,单点修改.不强制在线. 注释:$1\le n,m\le 10^5$. 想法: 带修改莫队裸题. 如果没有修改操作的话,我们就正常按照莫队一样左右移动区间即可. 有了修改操作的话,我们把块变成$n^{\frac{2}{3}}$,关键字变成:左端点所在块.右端点所在块和时间戳. 然后暴力就行了. Code: #include <iostream> #include <cstdio> #include &

F. Machine Learning 带修端点莫队

F. Machine Learning time limit per test 4 seconds memory limit per test 512 megabytes input standard input output standard output You come home and fell some unpleasant smell. Where is it coming from? You are given an array a. You have to answer the

【Luogu P4074】[WC2013]糖果公园(树上带修改莫队)

题目描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩. 糖果公园的结构十分奇特,它由 \(n\) 个游览点构成,每个游览点都有一个糖果发放处,我们可以依次将游览点编号为 \(1\) 至 \(n\).有 \(n-1\) 条双向道路连接着这些游览点,并且整个糖果公园都是连通的,即从任何一个游览点出发都可以通过这些道路到达公园里的所有其它游览点. 糖果公园所发放的糖果种类非常丰富,总共有 \(m\) 种,