BZOJ5443:[CEOI2018]Lottery
我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5443
这题能在暴力美学分组中占压轴地位,是不简单的。我从未见过如此灵性的暴力题目(也许是我太弱了题目写少了)。
我们令\(ans[j][i]\)表示与串\([i,i+l-1]\)距离为\(j\)的串的个数,最暴力的方法显然是直接\(O(n^2*l)\)去匹配的。
但是其中我们会对一些字符进行若干次重复的比较。比如\([1,3]\)和\([2,4]\)匹配时以及\([2,4]\)和\([3,5]\)都会判断\(a[3]\)是否等于\(a[3]\)。很显然这种冗余的操作是不优的。那么我们怎么减少这样的操作呢?
性质:如果我们已经知道了\([l1,r1]\)与\([l2,r2]\)的距离,那么我们可以在\(O(1)\)时间内算出\([l1+1,r1+1]\)与\([l2+1,r2+1]\)的距离。设前者为\(s\),后者为\(t\),那么\(t=s-(a[l1]!=a[l2])+(a[r1+1]!=a[r2+1])\)。
也就是说,我们可以在\(O(n)\)的时间内匹配完\(n\)条子串。
我们枚举一个\(len\),令\(h1\)为\(1\),\(h2\)为\(h1+len\),然后暴力匹配\([h1,h1+l-1]\)和\([h2,h2+l-1]\),再在\(O(n)\)的时间内把所以起点下标差为\(len\)的所以串对匹配完并且统计答案。
枚举\(len\)的复杂度乘以匹配的复杂度为\(O(n^2)\),我们成功消去了一个\(l\)!
但是这题还卡空间……所以\(ans\)数组开不了那么大。
可是出题人关上了一扇门,却为我们留了一扇窗。
\(query\)的次数很小。我们可以将\([1,l]\)之内的所有数字都找到离自己最近的大于等于自己的\(k\),用一个\(pos[i]\)记录这个\(k\)。然后每次匹配出来距离为\(dis\),我们就把答案累计到\(ans[pos[dis]][i]\)里去,最后前缀和一下,就可以求出所有的\(query\)了。
时间复杂度:\(O(n^2)\)
空间复杂度:\(O(nq)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e4+5;
bool v[maxn];
int n,m,l,cnt;
int ans[101][maxn];
int a[maxn],k[101],pos[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
void solve() {
for(int len=1;len<=n-l;len++) {//枚举len
int res=0,h1=1,h2=h1+len;//res记录当前两个串的距离,h1是第一个串的起点,h2是第二个串的起点
for(int i=0;i<l;i++)
if(a[h1+i]!=a[h2+i])res++;
ans[pos[res]][h1]++;
ans[pos[res]][h2]++;//答案累计到ans[pos[res]][h1]和ans[pos[res]][h2]里
while(1) {
if(h2+l>n)break;//如果h2往后没有l那么长了就break
res-=(a[h1]!=a[h2]);
res+=(a[h1+l]!=a[h2+l]);//O(1)转移
h1++;h2++;
ans[pos[res]][h1]++;
ans[pos[res]][h2]++;//累计答案
}
}
}
int main() {
n=read();l=read();
for(int i=1;i<=n;i++)
a[i]=read();
m=read();pos[1]=1;//pos[1]等于1
for(int i=1;i<=m;i++)
k[i]=read(),v[k[i]]=1;//我这里用差分的方法求每个数的pos
for(int i=2;i<=l;i++)
pos[i]=pos[i-1]+v[i-1];//如果是在(k[i],k[i+1]]之间的数,pos[i]就是i+1
solve();
for(int i=1;i<=n-l+1;i++)
for(int j=1;j<=m;j++)
ans[j][i]+=ans[j-1][i];//前缀和统计答案
for(int i=1;i<=m;i++) {
for(int j=1;j<=n-l+1;j++)
printf("%d ",ans[pos[k[i]]][j]);//离线输出答案
puts("");
}
return 0;
}
BZOJ5443:[CEOI2018]Lottery的更多相关文章
- xcode6中如何添加pch文件
在Xcode6之前,新建一个工程的时候,系统会帮我们自动新建一个以工程名为名字的pch (precompile header)文件,在开发过程中,可以将那些整个工程都广泛使用的头文件包含在该文件下,编 ...
- dotNet core 应用部署至 centos(超详解附截图)
文章来源:公众号-智能化IT系统. 需要安装的插件以及支撑架构 1.dotnetSDK dotnet 相关命令是属于 .NET Core command-line (CLI) 的一部分,Microso ...
- 7.Mysql存储引擎
7.表类型(存储引擎)的选择7.1 Mysql存储引擎概述 mysql支持插件式存储引擎,即存储引擎以插件形式存在于mysql库中. mysql支持的存储引擎包括:MyISAM.InnoDB.BDB. ...
- 开放通用Api,总有你喜欢的
接口文档 目录 通用 更新记录 接口列表 一.福彩-双色球接口 指定期号中奖号码 最新中奖号码信息 获取双色球中奖信息列表 二.节假日及万年历 指定日期的节假日及万年历信息 指定多个日期的节假日及万年 ...
- .netcore部署centos
前言:最近公司有个项目用 .netcore开发的项目,然后闲的没事就研究如果发布到Linux系统上 需要安装的插件以及支撑架构 1.dotnetSDK 2.jexus Jexus 是Linux平台上 ...
- 初次接触python时,整理的一些基础操作
1.window下python简单使用 (1).使用工具网址 https://jingyan.baidu.com/article/9f7e7ec0ec2e676f2915545f.html (2).各 ...
- 如何用 Python 写一个简易的抽奖程序
不知道有多少人是被这个头图骗进来的:) 事情的起因是这样的,上周有同学问小编,看着小编的示例代码敲代码,感觉自己也会写了,如果不看的话,七七八八可能也写的出来,但是一旦自己独立写一段程序,感觉到无从下 ...
- 利用Python写一个抽奖程序,解密游戏内抽奖的秘密
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 极客挖掘机 PS:如有需要Python学习资料的小伙伴可以加点击下 ...
- java web 开发三剑客 -------电子书
Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知In ...
随机推荐
- iOS设备获取总结
1.获取iOS设备的各种信息 // 这个方法后面会列出来 NSString *deviceName = [self getDeviceName]; NSLog(@"设备型号-->%@& ...
- Residual (numerical analysis)
In many cases, the smallness of the residual means that the approximation is close to the solution, ...
- term frequency–inverse document frequency
term frequency–inverse document frequency
- python爬虫之Selenium
Selenium的使用 #!/usr/bin/env python # -*- coding:utf-8 -*- """ Selenium是一个第三方模块,可以完全模拟用 ...
- centos修改mysql密码或者进入mysql后解决Access denied for user ''@'localhost' to database 'mysql错误
原因是MySQL的密码有问题 用mysql匿名用户可以进入数据库,但是看不见mysql数据库. 解决办法:具体操作步骤:关闭mysql:# service mysqld stop然后:# mysqld ...
- linux shell 中数组使用方法介绍
linux shell在编程方面比windows 批处理强大太多,不管是在循环.运算.已经数据类型方面都是不能比較的. 以下是个人在使用时候,对它在数组方面一些操作进行的总结. 1.数组定义 [che ...
- Django中日志管理
在settings中设置日志的相关信息,然后再逻辑代码区就可以保存相应的信息了 #简单设置: LOGGING = { 'version': 1, 'disable_existing_loggers': ...
- IOS 代码风格习惯 总结1
从我大三下学期开始工作开始, 几乎都是孤独的开发 因为身边开发ios 不多 ,除了学习开源的代码优秀风格技巧 剩下的 就是自己造, 所以 养成了 好多不好的习惯. 本知道面向对象的好处 ,但是实际开 ...
- c++之默认参数的函数
默认参数,看个例子就明白了 int add(int a=5,int b=6,z=3): int main(){ add():// 全部默认 add(1,5)://第三个参数默认 add(1,2,3): ...
- 每天一个Linux命令(3)mkdir命令
mkdir命令用来创建目录. (1)用法: 用法: mkdir [选项]... 目录... (2)功能: 功能: 若指定目录不存在则创建目录 该命令创建由dirname命名的目录.如果 ...