题意:

长度为 nnn 的序列,每个点都有一个颜色,一共有 CCC 个颜色,支持两种操作,第一种给出 lrxl\ r\ xl r x,将区间 [l,r][l,r][l,r] 全部染成 xxx,第二种给出一个 xxx,询问 xxx 颜色一共在序列中出现了多少次。

所有操作结束后,还要查询每种颜色出现的次数,给出最多出现的次数。(1≤n,C,m≤105)(1\leq n,C,m\leq 10^5)(1≤n,C,m≤105)


思路:

非常明显的区间推平操作,应该使用珂朵莉树进行解决,即用 setsetset 维护每一块相同区域。

老司机树是可以的,但是并没有采用,还是使用了分块的方法,虽然 TTT 的飞起…一开始的想法是给每个块记一个 mapmapmap,标记每个块中各个数字出现的次数,如果整个块被赋值了,就 map.clear()map.clear()map.clear()。但是 TTT 的不行,第 636363 个点怎么也过不去…

后来采用了完全的暴力分块,即每个块打个 lazylazylazy,如果 lazylazylazy 不为 000,则整个块中所有点大小均为 lazylazylazy。如果 lazylazylazy 为 000,则暴力修改、查询。那么如何分析这个做法的时间复杂度呢?

一共两种操作,修改操作每次最多涉及 n\sqrt nn​ 个块,如果块被完全覆盖,O(1)O(1)O(1) 打上标记,如果块只被部分覆盖,下放标记 O(n)O(\sqrt n)O(n​),修改点值 O(n)O(\sqrt n)O(n​),由于每次最多只有 222 个块被部分覆盖,最多 n\sqrt nn​ 个块被完全覆盖,因此修改操作总时间复杂度为 O(n)O(\sqrt n)O(n​)。

而对于查询操作,如果该块被打上了标记,则查询复杂度为 O(1)O(1)O(1),如果没有打上标记,则直接暴力查询,时间复杂度为 O(n)O(\sqrt n)O(n​)。此题是修改与查询次数一致,而修改操作每次最多使得 222 个块标记消失。因此可以发现,我们可以故意设置数据使得此种做法 TLETLETLE,即利用修改操作使得所有块的 lazylazylazy 标记消失,然后每次查询颜色时就会遍历所有块,可以将时间复杂度卡成 O(n2)O(n^2)O(n2)。(不过此题数据较水,此种方法也可以过,而且很快,390ms390\ ms390 ms 即可通过…)

因此正确的做法是当块没有 lazylazylazy 标记时,为了避免直接暴力询问,我们对于每个块记录一个 unordered_mapunordered\_mapunordered_map,查询复杂度为 O(1)O(1)O(1)。修改复杂度会变成 O(n∗log(n))O(\sqrt n*log(n))O(n​∗log(n)),查询复杂度为 O(n)O(\sqrt n)O(n​),但是避免了被卡的可能。(790ms790\ ms790 ms 可以通过)


总结:

对于一些不太常见的数据结构问题,一定要尝试考虑分块,因为分块方法用途很多,而且算法核心是暴力。

而对于分块算法,一定要多多尝试,你可能觉得这样分块会被你故意构造的一组数据卡成 O(n2)O(n^2)O(n2),但是出题人未必就考虑到了你的这种做法,因此一定要多尝试,不要只去尝试那些 O(n∗logn∗n)O(n*logn*\sqrt n)O(n∗logn∗n​) 的算法。当然如果能直接想到 O(n)O(\sqrt n)O(n​) 的算法则是最好的!


代码1:(390 ms)

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a);
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define per(i,a,b) for(int i = a; i >= b; i--)
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
typedef long long ll;
typedef double db;
const int N = 1e5+10;
const db EPS = 1e-9;
using namespace std;void dbg() {cout << "\n";}
template<typename T, typename... A> void dbg(T a, A... x) {cout << a << ' '; dbg(x...);}
#define logs(x...) {cout << #x << " -> "; dbg(x);}int n,m,a[N],L[N],R[N],pos[N],cnt,sz,lazy[N],num[N];
unordered_map<int,int> mp[1010];void change(int l,int r,int x){rep(i,pos[l],pos[r]){if(L[i] >= l && R[i] <= r){// mp[i].clear();// mp[i][x] = R[i]-L[i]+1;lazy[i] = x;}else{if(lazy[i]){rep(j,L[i],R[i]) a[j] = lazy[i];lazy[i] = 0;}rep(j,max(l,L[i]),min(R[i],r)){// mp[i][a[j]]--;// mp[i][x]++;a[j] = x;}}}
}int ask(int x){int ans = 0;rep(i,1,cnt){if(lazy[i]){if(lazy[i] == x) ans += R[i]-L[i]+1;}else{rep(j,L[i],R[i])if(a[j] == x) ans++;}}return ans;
}int main()
{int h; scanf("%d%d%d",&n,&h,&m);sz = sqrt(n);cnt = n/sz;if(n%sz != 0) cnt++;rep(i,1,cnt){L[i] = sz*(i-1)+1;R[i] = min(sz*i,n);mp[i][1] = R[i]-L[i]+1;}rep(i,1,n) pos[i] = ((i-1)/sz)+1;rep(i,1,n) a[i] = 1;while(m--){ll p,x,a,b;scanf("%lld%lld%lld%lld",&p,&x,&a,&b);ll s = ask(p);ll m1 = (a+s*s)%n;ll m2 = (a+(s+b)*(s+b))%n;change(min(m1,m2)+1,max(m1,m2)+1,x);}rep(i,1,cnt)if(lazy[i]){rep(j,L[i],R[i]) a[j] = lazy[i];lazy[i] = 0;}rep(i,1,n)num[a[i]]++;int maxx=0;rep(i,1,h)maxx = max(maxx,num[i]);printf("%d\n",maxx);return 0;
}

代码2:(790 ms)

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a);
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define per(i,a,b) for(int i = a; i >= b; i--)
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
typedef long long ll;
typedef double db;
const int N = 1e5+10;
const db EPS = 1e-9;
using namespace std;void dbg() {cout << "\n";}
template<typename T, typename... A> void dbg(T a, A... x) {cout << a << ' '; dbg(x...);}
#define logs(x...) {cout << #x << " -> "; dbg(x);}int n,m,a[N],L[N],R[N],pos[N],cnt,sz,lazy[N],num[N];
unordered_map<int,int> mp[510];void change(int l,int r,int x){rep(i,pos[l],pos[r]){if(L[i] >= l && R[i] <= r) lazy[i] = x;else{if(lazy[i]){std::unordered_map<int,int> tmp;mp[i].swap(tmp); //设置一个空的交换,类似于clearmp[i].reserve(1000); //预留map中元素个数mp[i].rehash(1000); //给元素个数预留足够的bucket用于hashmp[i][lazy[i]] = R[i]-L[i]+1;rep(j,L[i],R[i]) a[j] = lazy[i];lazy[i] = 0;}rep(j,max(l,L[i]),min(R[i],r)){mp[i][a[j]]--;mp[i][x]++;a[j] = x;}}}
}int ask(int x){int ans = 0;rep(i,1,cnt){if(lazy[i]){if(lazy[i] == x) ans += R[i]-L[i]+1;}else ans += mp[i][x];}return ans;
}int main()
{int h; scanf("%d%d%d",&n,&h,&m);sz = sqrt(n);cnt = n/sz;if(n%sz != 0) cnt++;rep(i,1,cnt){L[i] = sz*(i-1)+1;R[i] = min(sz*i,n);mp[i][1] = R[i]-L[i]+1;}rep(i,1,n) pos[i] = ((i-1)/sz)+1;rep(i,1,n) a[i] = 1;while(m--){ll p,x,a,b;scanf("%lld%lld%lld%lld",&p,&x,&a,&b);ll s = ask(p);ll m1 = (a+s*s)%n;ll m2 = (a+(s+b)*(s+b))%n;change(min(m1,m2)+1,max(m1,m2)+1,x);}rep(i,1,cnt)if(lazy[i]){rep(j,L[i],R[i]) a[j] = lazy[i];lazy[i] = 0;}rep(i,1,n)num[a[i]]++;int maxx=0;rep(i,1,h)maxx = max(maxx,num[i]);printf("%d\n",maxx);return 0;
}

【Gym-101889 D】Daunting device【分块】相关推荐

  1. 【最小生成树+LCA】Imperial roads

    http://codeforces.com/gym/101889 I 先跑一遍最小生成树,把经过的边和答案记录下来 对于每个询问的边,显然如果处于MST中,答案不变 如果不在MST中,假设这条边连上了 ...

  2. 【2019.09.21】ICPC Latin American Regional-2017

    提交地址:https://codeforces.com/gym/101889 解题数:6/13 题目: A: B: C: D: E: F: G: H: I: J: K: L: M: 感觉整场下来自己的 ...

  3. linux能修改用户的权限,linux怎样修改用户权限

    ls -l  查看目录下的文件详细信息 ll 同上 whoami 功能说明:先似乎用户名称. 语 法:whoami [--help][--version] 补充说明:显示自身的用户名称,本指令相当于执 ...

  4. Jeson TX2刷机(Jetpack 4.4版本)及镜像备份与恢复的巨详细教程

    JETSON TX2镜像备份与恢复以及刷机的巨详细教程(Jetpack 4.4版本) JETSON TX2镜像备份与恢复以及刷机的巨详细教程(Jetpack 4.4版本) 刷机前的絮絮叨叨和准备工作 ...

  5. Ubuntu下常用强化学习实验环境搭建(MuJoCo, OpenAI Gym, rllab, DeepMind Lab, TORCS, PySC2)

    原文地址:http://blog.csdn.net/jinzhuojun/article/details/77144590 和其它的机器学习方向一样,强化学习(Reinforcement Learni ...

  6. CUDA精进之路(一):图像处理——大图像分块处理(包括求均值、最大值)

    引言 在我的第一篇文章中我简单介绍了CUDA以及我的一些个人学习见解,在本文中我将开始正式开始CUDA实践之旅,众做周知CUDA目前应用的领域十分广泛,它能把一些普通的CPU代码提速几十倍甚至几百倍. ...

  7. 强化学习初探 DQN+PyTorch+gym倒立摆登山车

    文章目录 1.随便说几句 2.为什么选择DQN作为第一个入手的模型 2.工具准备 3.实现思路 3.1.环境采样 3.2 Reward设计 3.3 Q值近似计算 3.4 主循环 4.代码 5.参考文献 ...

  8. 常用增强学习实验环境 I (MuJoCo, OpenAI Gym, rllab, DeepMind Lab, TORCS, PySC2)

    常用增强学习实验环境 I (MuJoCo, OpenAI Gym, rllab, DeepMind Lab, TORCS, PySC2) 标签: 强化学习OpenAI GymMuJoCoStarCra ...

  9. 基于DQN与gym的小车爬坡训练

    文章目录 前言 一.pytorch环境搭建 1.GPU下的环境搭建 2.CPU下的环境搭建 3.其他依赖包 二.环境学习 1.观测 2.行为 3.物理交互 4.奖励 5.小车初始状态 6.终止条件 G ...

  10. hackthebox-buff(gym渗透 端口转发 cloudme 缓冲区溢出 )

    1.扫描 masscan快速全局扫,nmap具体扫.7680不知道,8080是web进去搜集信息. C:\root> masscan -p1-65535,U:1-65535 10.10.10.1 ...

最新文章

  1. C++中public protected private的区别
  2. jzoj4228-C【dp】
  3. .rpt文件内容读取java_好程序员前端教程-nodejs如何读取文件夹目录的内容
  4. jenkins java必装插件_Jenkins(三)安装相关插件
  5. 【Python】:拓展Queue实现有序不重复队列
  6. 阿里张勇《人民日报》刊发署名文章:抓住数字新基建的机遇
  7. python编程从入门到实践(第2版)第二章练习题解答
  8. 样本大小的确定_显着功效样本大小效应大小之间的关系
  9. C/C++编程笔记:C语言编程知识要点总结!大一C语言知识点(全)
  10. 泛泰A870K去掉相机快门声音的方法
  11. 纪念 | 永远的凌晨四点钟
  12. 计算机课玩游戏检讨书,上微机课玩游戏检讨书.doc
  13. Proxmox集群网络配置
  14. 鲁班图片压缩实现仿微信九宫格选择图片效果
  15. java mail实现smtp登录验证
  16. 在线思维导图Processon部分截图
  17. VUE+ECharts 制作饼图
  18. php编辑器怎么修改字体,vscode怎么改变字体
  19. 【推荐系统】POLY2、FM、FFM模型的进化之路
  20. ThreadPoolTaskExecutor @Async调用方法

热门文章

  1. apache 目录认证
  2. 批处理处理oracle数据库脚本导入
  3. Java的反射 基础+简单复制对象实例
  4. CISCO路由器的备份与还原(2)
  5. (转)优秀网站源码、编程源码下载网站大集中
  6. Mac配置腾讯云服务器SSH秘钥免登陆
  7. html执行严格语法标准,JS语法(ES6)
  8. php xml三级联动,jquery+xml实现三级联动步骤详解
  9. pyqt5 tablewidget 设置行高_Python+PyQt5基础开发(10)
  10. linux自带的cpu监测工具,Linux CPU实时系统监控工具mpstat