CJB的大作
Description
给你一个长度不超过100的字符串。一共进行\(N\)次操作,第\(i\)次操作是将当前字符串复制一份接到后面,并将新的一份循环移位\(k_i\)(\(1 \le k_i \le 100\))次。给出\(M\)(\(1 \le M \le 100000\))个询问,每次询问所有操作完成之后,\([l,r]\)中,某个字母出现了多少次。其中\(1 \le l \le r \le 10^{18}\)。
Solution
我开场就写了2个小时的暴力分治,并惊喜地发现单个询问可以秒出。结果一组询问需要0.01s,拿到了40分的好成绩。
首先\(N\)只有约前60项是有意义的,因此总操作数大约是60次。
这种字符串变换题目要重点观察变换前和变换后是否有一大块一大块是相等的。比如某次操作前,字符串是\(S\),\(A\)和\(B\)是\(S\)的两块(即\(S=AB\))其中B的长度恰好是这次操作的偏移值。那么操作完之后,字符串的变化如下:
\]
既然只有60次操作,而每次操作的\(B\)的长度不超过100,我们完全可以算出每次操作的\(B\)串。即枚举每个字符,反向模拟这个字符是怎么从原串变换来的,即可在一个\(\log\)的时间确定每个字符是什么。
将询问查分,则我们要求\([1,n]\)中有多少个\(c\)字符。
考虑从最后一次操作开始递归向前计算(其实应该是:最早的一次操作,满足操作后串长不小于\(n\))。
如果\(n\)落在左边的\(AB\)内:那么直接递归前一次操作,返回其答案。
如果\(n\)落在右边的\(B\)内:左半边\(AB\)的答案显然,就是原串中这个字符的数量乘上左半边有多少个原串。对于右边部分,我们预处理出每次操作中\(B\)的字母前缀和,\(O(1)\)可询问\(B\)前缀字母数量。两者加起来就是答案。
如果\(n\)落在右边的\(A\)内:\(ABB\)的答案可以用上一个情况的思路直接算,而最右边的\(A\)的答案,其实就是最左边的\(A\)的对应位置的答案。和第一种情况一样,我们递归前一次操作即可知道这部分的答案。
我们发现总分治递归层数不会超过有效操作次数。因此这题可以在\(\mathcal O(M\log 10^{18})\)内解决。
Code
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
namespace IO{
const int S=20000005;
char buffer[S];
int pos;
void Load(){
pos=0;
fread(buffer,1,S,stdin);
}
char getChar(){
char res=buffer[pos++];
if(pos>=S)
Load();
return res;
}
ll getLong(){
ll x=0,f=1;
char c=getChar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getChar();}
while('0'<=c&&c<='9'){x=x*10+c-'0';c=getChar();}
return x*f;
}
int getStr(char *str){
int len=0;
for(char c=getChar();'a'<=c&&c<='z';c=getChar())
str[len++]=c;
return len;
}
}
using IO::getLong;
using IO::getStr;
const int N=110,B=70,C=26;
const ll UP=2e18;
char str[N];
int slen;
int n,m,off[100005];
int pre[N][C],f[B][N][C];
void readData(){
slen=IO::getStr(str+1);
n=getLong(); m=getLong();
for(int i=1;i<=n;i++)
off[i]=getLong();
}
inline ll get_len(int bit){
return 1ll*slen*(1ll<<bit);
}
char get_char(int bit,ll x){
if(bit==0)
return str[x];
ll mid=get_len(bit-1);
if(x<=mid)
return get_char(bit-1,x);
ll cut=mid+off[bit];
if(x<=cut)
return get_char(bit-1,mid-(cut-x));
else
return get_char(bit-1,x-cut);
}
void precount(){
for(int i=1;i<=slen;i++){
for(int j=0;j<26;j++)
pre[i][j]=pre[i-1][j];
pre[i][str[i]-'a']++;
}
for(int i=1;get_len(i)<UP;i++){
ll mid=get_len(i-1);
off[i]%=mid;
for(int j=1;j<=off[i];j++){
for(int k=0;k<26;k++)
f[i][j][k]+=f[i][j-1][k];
char c=get_char(i-1,mid-off[i]+j);
f[i][j][c-'a']++;
}
}
}
ll solve(int bit,ll n,int c){
if(bit==0)
return pre[n][c];
ll mid=get_len(bit-1),cut=mid+off[bit];
if(n<=mid)
return solve(bit-1,n,c);
if(n<=cut)
return 1ll*pre[slen][c]*(1ll<<(bit-1))+f[bit][n-mid][c];
else
return 1ll*pre[slen][c]*(1ll<<(bit-1))+f[bit][cut-mid][c]+solve(bit-1,n-cut,c);
}
ll calc(ll n,char c){
if(!n)
return 0;
int bit;
for(bit=0;get_len(bit)<n;bit++);
return solve(bit,n,c-'a');
}
void answerQuery(){
ll l,r;
char c[2];
for(int i=1;i<=m;i++){
l=getLong(); r=getLong(); getStr(c);
printf("%lld\n",calc(r,c[0])-calc(l-1,c[0]));
}
}
int main(){
IO::Load();
readData();
precount();
answerQuery();
return 0;
}
CJB的大作的更多相关文章
- NOIp2018模拟赛三十五
两道大数据结构把我砸懵 成绩:未提交 Orz xfz两道正解 A:[BZOJ4049][CREC2014B]mountainous landscape B:CJB的大作(CF改编题)
- 转载部长一篇大作:常用排序算法之JavaScript实现
转载部长一篇大作:常用排序算法之JavaScript实现 注:本文是转载实验室同门王部长的大作,找实习找工作在即,本文颇有用处!原文出处:http://www.cnblogs.com/ywang172 ...
- cjb
输入216.194.70.6 ,进入到是cjb.net的主页,并不是shell.cjb.net ,进入主页后点击shell,就进不去了 分析:shell.cjb.net被DNS污染了 解法:hosts ...
- Bishop的大作《模式识别与机器学习》Ready to read!
久仰Bishop的大作“Pattern Recognition and Machine Learning”已久,在我的硬盘里已经驻扎一年有余,怎奈惧其页数浩瀚,始终未敢入手.近日看文献,屡屡引用之.不 ...
- 当今游戏大作share的特性大盘点
极品游戏制作时的考虑要素大盘点 不知不觉入坑Steam已近4年,虽然说Steam的毒性让很多人走向一条不归路,但是想我这样即使"中毒"还是很快乐很感恩的.那么本期文章就谈谈我对其中 ...
- 深入Guerrilla Games解密次世代开山大作《杀戮地带暗影坠落》(The technology of Killzone Shadow Fall)
文章摘要:这几天终于有时间,把全文翻译完了,自己感觉不是太满意,不过大家能看懂就好,就当一个学习的机会.整篇文章通过SONY第一方游戏工作室Guerrilla Games主创的语录,为我们展现了次世代 ...
- 关于Delphi中的字符串的浅析(瓢虫大作,里面有内存错误的举例)
关于Delphi中的字符串的浅析 只是浅浅的解析下,让大家可以快速的理解字符串. 其中的所有代码均在Delphi7下测试通过. Delphi 4,5,6,7中有字符串类型包括了: 短字符串(Short ...
- 採訪The Molasses Flood:BioShock Infinite 游戏之后又一大作
Xsolla有幸与Flame in the Flood游戏的开发人员之中的一个-----Forrest Dowling进行了採訪,Flame in the Flood这款非常棒的游戏在Kickstar ...
- 5月,专用程序猿的经典大作——APUE
五一小长假刚刚过去,收回我们游走的心.開始你们的读书旅程吧! 本期特别推荐 经典UNIX著作最新版. 20多年来,这本书帮助几代程序猿写出强大.高性能.可靠的代码. 第3版依据当今主流系统进行更新,更 ...
随机推荐
- 使用navicat连接mysql时报错:2059 - authentication plugin 'caching_sha2_password'
首先从本地登录mysql数据库,进入mysql控制台,输入如下命令: ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_passwo ...
- Tomcat端口被占用解决方案
Tomcat端口被占用解决方法 1.在dos下,输入 netstat -ano|findstr 8080 //说明:查看占用8080端口的进程,显示占用端口的进程 2.taskkill /pid 19 ...
- 20155323刘威良《网络对抗》Exp5 MSF基础应用
20155323刘威良<网络对抗>Exp5 MSF基础应用 实践内容 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实 ...
- EasyUI-Tree的使用
在web开发中,树是比较常见的东西.以前用过zTree,也用过EasyUI-Tree,过了好久后发现都忘记怎么用了. 这几天重新回顾了EasyUI-tree的使用,在此将相关知识点记录 ...
- Data Consistency Primer
云应用通常来说,使用的数据很多都是分散的,来自不同的数据仓库.在这种环境下,管理和保持数据一致性是很复杂的,无论是在并发跟可用性上都可能出问题.开发者有的时候就需要为了强一致性而牺牲可用性了.这也就意 ...
- 几个不常用的 Web API
1. 设备震动 vibrate Navigator.vibrate() 方法使设备(有震动硬件)产生有频率的震动.若设备不支持震动,该方法将无效.若某震动方式已经在进行中(当该方法调用时),则前一个震 ...
- VirtualBox虚拟机怎么导入已经存在的vdi文件
VirtualBox虚拟机怎么导入已经存在的vdi文件 第一章 1.原因 早上一不小心将virtualBox 卸载了,(不知道怎么了, 里面得虚拟机全部都没有了,但是vdi文件还在) 2.解决办法 直 ...
- webpack 支持的模块方法
在webpack中支持的模块语法风格有:ES6,commonJS和AMD ES6风格(推荐) 在webpack2中,webpack支持ES6模块语法.这意味着在没有babel等工具处理的情况下你就可以 ...
- torchvision 批量可视化图片
1.1 简介 计算机视觉中,我们需要观察我们的神经网络输出是否合理.因此就需要进行可视化的操作. orchvision是独立于pytorch的关于图像操作的一些方便工具库. torchvision的详 ...
- Bootstrap 样式设计 栅格系统
.col-xs- 超小屏幕 手机 (<768px) .col-sm- 小屏幕 平板 (≥768px) .col-md- 中等屏幕 桌面显示器 (≥992px) .col-lg- 大屏幕 大桌面显 ...