cf 472G Design Tutorial: Increase the Constraints 分块+压位/FFT
题目大意
给出两个\(01\)序列\(A\)和\(B\)
哈明距离定义为两个长度相同的序列中,有多少个对应位置上的数字不一样
"00111" 和 "10101"的距离为2
\(Q\)次询问,每次询问给出\(p_1,p_2,len\)
求\(a{p_1},a{p_1+1}...a_{p_1+len-1}\) 和 \(b_{p_1},b_{p_1+1}...b_{p_1+len-1}\)两个子串的哈明距离
注意:本题中的序列是从\(0\)开始编号的:\(a_0,a_1,...,a_{n-1}\)
\(1\leq |A|.|B|\leq 2*10^5,1\leq Q\leq 4*10^5\)
\(0 \leq p_1 \leq |a| - len\),\(0 \leq p_2 \leq |b| - len\)
分析
哈明距离可以转化成异或后有多少个\(1\)
考虑如何快速的比较两个字符串
我们先求出每个位置往后\(32\)位/\(64\)位的压位后的值
这样之后再暴力的复杂度就变成了\(\frac {len} {32}\)
我们再考虑对\(A\)串分块
每长度\(T\)分一块
预处理\(dif[i][j]\)表示\(A\)中第\(i\)块整个块 和 \(B\)中\(j\)开始的长度为\(T\)的串的哈明距离
\(O(\frac n T *m *\frac T {32})=O(\frac {n*m} {32})\)
对于询问
左右两边暴力扫\(O(T)\)
中间块内的用预处理直接求\(O(\frac n T)\)
算出来\(T=\sqrt n\)最优
同时T要是\(32\)/\(64\)的倍数
原题空间256M好像开不到\(n*\sqrt n\)的数组要调调参数
优化
块内的复杂度\(O(\frac {n*m} {32})\)小心脏承受不住
可以用FFT优化
s[i]==1的FFT数组中设为1,否则设为-1
将块中串反过来,卷积一波
求出来的值就是\(同-异\)
而块的大小为\(同+异\)
\(\frac {同+异-(同-异)} 2=异\)
这样就可以不用1算一次,0算一次再用总数减常数那么大了
结果越跑越慢
各种调参数到5000左右最快了
组合
如果两个算法合起来就完美了(越写越慢还好意思说)
注意
unsigned满位后左移一位可以看作把最高位扔掉后左移一位
bitset的count()是暴力
正确姿势:预处理1<<16内每个数有多少个1,分段算
FFT有负数用round()取整
solution(分块+压位)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <bitset>
using namespace std;
typedef unsigned long long ull;
const int S=450;
const int M=200003;
const int N=1<<16;
inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
char s[M];
char t[M];
int n,m,Q;
int sn,MX;
int cnt[N];
ull aw[M],bw[M];
int dif[S][M];
int loc(int x){
return x/sn+1;
}
int getL(int x){
return (x-1)*sn;
}
int getR(int x){
return x*sn-1;
}
int getP(int x){
int L=getL(loc(x));
return x-L+1;
}
int main(){
int i,j,k,BL,BR,L,R,x,y,z,len;
scanf("%s%s",s,t);
n=strlen(s); m=strlen(t);
sn=448; MX=loc(n);
for(i=0;i<N;i++) cnt[i]=cnt[i>>1]+(i&1);
for(i=0;i+63<n;i++)
for(j=i;j<i+64;j++)
aw[i]=aw[i]<<1|(s[j]=='1');
for(i=0;i+63<m;i++)
for(j=i;j<i+64;j++)
bw[i]=bw[i]<<1|(t[j]=='1');
int ful=N-1;
for(i=1;i<=MX;i++){
L=getL(i);
if(L+sn-1>=n) break;
for(j=0;j+sn-1<m;j++){
x=L,y=j;
for(k=7;k>0;k--){
ull tp=aw[x]^bw[y];
dif[i][j]+=cnt[tp&ful]+cnt[tp>>16&ful]+cnt[tp>>32&ful]+cnt[tp>>48];
x+=64; y+=64;
}
}
}
Q=rd();
int ans;
while(Q--){
ans=0;
x=rd(),z=rd(),len=rd();
y=x+len-1;
BL=loc(x); BR=loc(y);
if(BL+1>=BR){
for(i=x;i<=y;i++) ans+=s[i]!=t[z+i-x];
}
else{
if(getL(BL)!=x) BL++;
if(getR(BR)!=y) BR--;
L=getL(BL); R=getR(BR);
for(i=BL;i<=BR;i++)
ans+=dif[i][z+getL(i)-x];
for(i=x;i<L;i++) ans+=s[i]!=t[z+i-x];
for(i=y;i>R;i--) ans+=s[i]!=t[z+i-x];
}
printf("%d\n",ans);
}
return 0;
}
solution(分块+FFT)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef double db;
const int N=262144;
const int S=207;
const int M=200003;
const db pi=acos(-1.0);
inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
char s[M];
char t[M];
int rev[N];
int n,m,Q;
int sn,MX;
struct CP{
db x,i;
CP(db xx=0.0,db ii=0.0){x=xx;i=ii;}
}a[N],b[N],c[N];
CP operator +(CP x,CP y){return CP(x.x+y.x,x.i+y.i);}
CP operator -(CP x,CP y){return CP(x.x-y.x,x.i-y.i);}
CP operator *(CP x,CP y){return CP(x.x*y.x-x.i*y.i,x.i*y.x+x.x*y.i);}
void FFT(CP *a,int fl){
int i,j,k;
CP W,Wn,u,v;
for(i=0;i<N;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(i=2;i<=N;i<<=1){
Wn=CP(cos(2*pi/i),fl*sin(2*pi/i));
for(j=0;j<N;j+=i){
W=CP(1,0);
for(k=j;k<j+i/2;k++,W=W*Wn){
u=a[k];
v=a[k+i/2]*W;
a[k]=u+v;
a[k+i/2]=u-v;
}
}
}
if(fl==1) return ;
for(i=0;i<N;i++) a[i].x/=N;
}
int dif[S][M];
int loc(int x){
return x/sn+1;
}
int getL(int x){
return max(1,(x-1)*sn);
}
int getR(int x){
return min(n,x*sn-1);
}
int getP(int x){
int L=getL(loc(x));
return x-L+1;
}
int main(){
int i,j,BL,BR,L,R,x,y,z,len;
scanf("%s%s",s+1,t+1);
n=strlen(s+1); m=strlen(t+1);
sn=5000; MX=loc(n);
for(i=0;i<N;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?(N>>1):0);
for(i=1;i<=m;i++) b[i]=(t[i]=='1')?1:-1;
FFT(b,1);
for(i=1;i<=MX;i++){
L=getL(i);
R=getR(i);
for(j=0;j<N;j++) a[j]=CP();
int tt=0;
for(j=R;j>=L;j--) a[++tt]=(s[j]=='1')?1:-1;
FFT(a,1);
for(j=0;j<N;j++) c[j]=a[j]*b[j];
FFT(c,-1);
int sss=R-L+1;
for(j=1;j<=m;j++) dif[i][j]=(sss-round(c[j+sss].x))/2;
}
Q=rd();
int ans;
while(Q--){
ans=0;
x=rd(),z=rd(),len=rd();
x++;z++;//ÎÒ´Ó 1 ´æ
y=x+len-1;
BL=loc(x);BR=loc(y);
if(BL+1>=BR){
for(i=x;i<=y;i++) ans+=(s[i]!=t[z+i-x]);
}
else{
if(getL(BL)!=x) BL++;
if(getR(BR)!=y) BR--;
L=getL(BL); R=getR(BR);
for(i=x;i<L;i++) ans+=(s[i]!=t[z+i-x]);
for(i=BL;i<=BR;i++)
ans+=dif[i][z+getL(i)-x];
for(i=y;i>R;i--) ans+=(s[i]!=t[z+i-x]);
}
printf("%d\n",ans);
}
return 0;
}
cf 472G Design Tutorial: Increase the Constraints 分块+压位/FFT的更多相关文章
- 【CF472G】Design Tutorial: Increase the Constraints
Description 给出两个01序列\(A\)和\(B\) 要求回答\(q\)个询问每次询问\(A\)和\(B\)中两个长度为\(len\)的子串的哈明距离 哈明距离的值即有多少个位置不相等 ...
- CF472G Increase the Constraints
Increase the Constraints 定义两个等长的01字符串的汉明距离为它们字符不同的对应位置的个数. 给你两个01串S,T,现在有q个询问,每次指定S,T中两个定长的子串询问它们的汉明 ...
- Codeforces #270 D. Design Tutorial: Inverse the Problem
http://codeforces.com/contest/472/problem/D D. Design Tutorial: Inverse the Problem time limit per t ...
- cf472D Design Tutorial: Inverse the Problem
D. Design Tutorial: Inverse the Problem time limit per test 2 seconds memory limit per test 256 mega ...
- cf472C Design Tutorial: Make It Nondeterministic
C. Design Tutorial: Make It Nondeterministic time limit per test 2 seconds memory limit per test 256 ...
- cf472B Design Tutorial: Learn from Life
B. Design Tutorial: Learn from Life time limit per test 1 second memory limit per test 256 megabytes ...
- cf472A Design Tutorial: Learn from Math
A. Design Tutorial: Learn from Math time limit per test 1 second memory limit per test 256 megabytes ...
- Codeforces Round #270--B. Design Tutorial: Learn from Life
Design Tutorial: Learn from Life time limit per test 1 second memory limit per test 256 megabytes in ...
- Qsys 设计流程---Qsys System Design Tutorial
Qsys 设计流程 ---Qsys System Design Tutorial 1.Avalon-MM Pipeline Bridge Avalon-MM Pipeline Bridge在slave ...
随机推荐
- 毛毛虫组【Beta】Scrum Meeting 1
第一天 日期:2019/6/23 前言 第一次会议: 时间:6月20日 地点:教9-C404机房 内容:此次会议主要确定组内成员具体分工,并对目标进行了初步的确定. 1.1 今日完成任务情况以及遇到的 ...
- eubacteria|endosymbiosis|基因转移
5.11线粒体和叶绿体是通过内共生进化而来的 初始细胞俘获有功能的真细菌(eubacteria)进入细胞内,该细菌逐渐演化为细胞器,这种现象称为内共生(endosymbiosis),所以该细胞器携带细 ...
- 简单的Datable转List方法
public static class DataTableUtils<T> where T : new() { public static List<T> ConvertToM ...
- mysql命令行复制数据库
为了方便快速复制一个数据库,可以用以下命令将db1数据库的数据以及表结构复制到newdb数据库创建新的数据库#mysql -u root -p123456 mysql>CREATE DATABA ...
- LeetCode(258) Add Digits
题目 Given a non-negative integer num, repeatedly add all its digits until the result has only one dig ...
- hihocoder1174 拓扑排序1
#1174 : 拓扑排序·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 由于今天上课的老师讲的特别无聊,小Hi和小Ho偷偷地聊了起来. 小Ho:小Hi,你这学期有选 ...
- Makefile基础(一)
在大型的C语言项目中,一般都是由多个源文件编译链接形成的可执行程序,而这些源文件的处理步骤,通常交给Makefile来管理,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后 ...
- kruskal - 倍增 - 并查集 - Luogu 1967 货车运输
P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...
- dubbo rpc filter实现剖析(二)
2.6.3版本,之前读的是2.4.9版本 本篇主要阐述dubbo rpc的filter的实现,包括作用,用法,原理,与Spring Cloud在这些能力的对比. 整个filter列表的获取过程在 co ...
- day05_03 字符串格式化
pycharm小技巧,一般情况下都需要在代码前注释以下作者以及创建日期 但是如何让软件默认生成呢? 格式化输出 可以用占位符 %s string的缩写 #__author:Administra ...