题目链接:点击查看

题目大意:给出一个长度为 n 的序列,其意义为第 i 秒需要看第 a[ i ] 种书,书架上可以供应无限种书,但是书桌有容量,当书桌上的容量达到上限后,如果还想从书架上拿新书来看,就必须要从书桌上拿最早不看的那本书还回去才行,每次拿书都会记为一个操作,问当书桌的容量分别为 1 ~ n 时,看完 n 次书的最小操作次数

题目分析:首先这个题目限制了每次换书只能舍弃最早不看的那本书,所以并不是一种最优性的决策,这也大大降低了题目的难度

单独考虑两个相同的书的位置分别为 l 和 r,计算一下 [ l , r ] 内有多少种不同种类的书,如果这个数量 num 大于等于桌子容量的话,那么显然在第 r 秒直接读第 l 秒剩下的书即可,对应的,当 num 小于桌子容量的话,那么第 r 秒必须重新去书架上拿书才行

这样一来问题就转换为了,区间内有多少个本质不同的数的个数,又因为每次遍历的都是一个前缀中的区间,所以可以直接维护一个树状数组或者线段树来求解,对于上一段中的每个 [ l , r ] 所计算出的 num,都会使书桌容量小于 num 的答案贡献加一,所以用差分数组统计一下就好了

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;int c[N],ans[N],pre[N],n;int lowbit(int x)
{return x&(-x);
}void add(int x,int val)
{for(int i=x;i<=n;i+=lowbit(i))c[i]+=val;
}int ask(int x)
{int ans=0;for(int i=x;i>0;i-=lowbit(i))ans+=c[i];return ans;
}void init()
{memset(c,0,sizeof(int)*(n+5));memset(ans,0,sizeof(int)*(n+5));memset(pre,0,sizeof(int)*(n+5));
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%d",&n);init();int t=0;for(int i=1;i<=n;i++){int num;scanf("%d",&num);if(pre[num]){int len=ask(i)-ask(pre[num]-1);ans[1]++;ans[len]--;add(pre[num],-1);}elset++;add(i,1);pre[num]=i;}for(int i=1;i<=n;i++){ans[i]+=ans[i-1];printf("%d%c",ans[i]+t,i==n?'\n':' ');}}return 0;
}

ZOJ - 4117 BaoBao Loves Reading(树状数组求区间内不同数的个数+思维)相关推荐

  1. 树状数组求区间和模板 区间可修改 参考题目:牛客小白月赛 I 区间

    从前有个东西叫树状数组,它可以轻易实现一些简单的序列操作,比如单点修改,区间求和;区间修改,单点求值等. 但是我们经常需要更高级的操作,比如区间修改区间查询.这时候树状数组就不起作用了,只能选择写一个 ...

  2. 牛客练习赛52.Galahad(树状数组维护区间不相同数的和)

    链接:https://ac.nowcoder.com/acm/contest/1084/B 来源:牛客网 Galahad 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K ...

  3. hdu2852(2009多校第四场) 树状数组求区间第k大的数 两种方法

    二分查找n*logn*logn 比较容易理解 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm& ...

  4. 【BZOJ】1012: [JSOI2008]最大数maxnumber 树状数组求区间最值

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1012 题意:维护一个数列,开始时没有数值,之后会有两种操作, Q L :查询数列末 ...

  5. 树状数组求区间和(区间均值)

    1658: O__O "- 就是那道中文题 Time Limit: 1 Sec Memory Limit: 128 MB [Submit][Status][Web Board] Descri ...

  6. [Split The Tree][dfs序+树状数组求区间数的种数]

    Split The Tree 时间限制: 1 Sec  内存限制: 128 MB 提交: 46  解决: 11 [提交] [状态] [讨论版] [命题人:admin] 题目描述 You are giv ...

  7. HDU 6681(树状数组统计平面内射线的交点个数)

    HDU 6681(树状数组,统计平面内射线的交点个数) 题目链接:传送门 题意:给出k条射线,求射线将n∗mn*mn∗m 的区域分成几个联通块.每两条射线的端点x坐标和y坐标都互不相同. 思路:根据 ...

  8. 树状数组求区间和 和 单点更新

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  9. SPOJ DQUERY 求区间内不同数的个数 主席树

    这题跟HDU3333差不多吧. 离线的做法很简单,不再说了 以前做过. 主席树的做法就比较暴力了.. 什么是主席树呢.. 其实是某种称号. 在该题中的体现是可持久化的线段树. 对于一个数 如果以前没出 ...

最新文章

  1. 磁共振线圈分类_磁共振硬件(二)主磁体分类
  2. 测度论相关概念(吐)
  3. 【CodeForces 577C】Vasya and Petya’s Game
  4. Collection中list集合的应用常见的方法
  5. 前端学习(1955)vue之电商管理系统电商系统之完成添加分类功能
  6. 吴恩达深度学习4.2笔记_Convolutional Neural Networks_深度卷积模型
  7. chap8_1 Render to texture in OGRE
  8. 辨异 —— 逻辑之辨、人文社科观念
  9. https://docs.python.org/3/
  10. C++11 外部模板
  11. 降维系列之 MDS多维缩放 与 ISOMAP 等度量映射
  12. ios safari 模拟器_Safari调试iOS应用
  13. TalkingData :如何做到30分钟内完成对数十亿受众数据的分析 | 会员专栏
  14. MessageBox confirm弹框确认和取消按钮的使用-回调
  15. 打造任何地方都能使用的markdown写作软件:Typora云端化
  16. Django+Mysql学生选课系统/学分管理系统
  17. 如何统计每个小时用户在线人数?
  18. 腾讯实时音视频SDK[三]:小程序端实现
  19. 安装声卡驱动报错,代码:0xe0000246
  20. Unity实战之见缝插针

热门文章

  1. 根据类名遍历数组的三种方法
  2. MySQL高级 - 内存优化 - 优化原则
  3. 存储过程语法 - 变量
  4. Nginx的location指令
  5. 中文和英文对应的字节
  6. 自定义线程池-java内置线程池构造方法介绍
  7. 类加载器-启动类加载器
  8. 解决cookie写入问题
  9. Spring Boot定时任务-Quartz基本使用
  10. log4j 2.x --LogManager