博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cf 472G Design Tutorial: Increase the Constraints 分块+压位/FFT
阅读量:5319 次
发布时间:2019-06-14

本文共 3580 字,大约阅读时间需要 11 分钟。

题目大意

给出两个\(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 
#include
#include
#include
#include
#include
#include
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
>1]+(i&1); for(i=0;i+63
=n) break; for(j=0;j+sn-1
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
R;i--) ans+=s[i]!=t[z+i-x]; } printf("%d\n",ans); } return 0;}

solution(分块+FFT)

#include 
#include
#include
#include
#include
#include
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
>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
=L;j--) a[++tt]=(s[j]=='1')?1:-1; FFT(a,1); for(j=0;j
=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
R;i--) ans+=(s[i]!=t[z+i-x]); } printf("%d\n",ans); } return 0;}

转载于:https://www.cnblogs.com/acha/p/6441079.html

你可能感兴趣的文章
【译】使用 CocoaPods 模块化iOS应用
查看>>
JavaScript中test函数
查看>>
设计模式之工厂方法模式
查看>>
计算机组成 计算机五大部件 计算器和存储器
查看>>
Chrom去掉"未选择任何文件"
查看>>
zdlzxg
查看>>
iOS上获得MAC地址
查看>>
Linux Samba安装与使用
查看>>
什么是智能dns解析
查看>>
企业架构 - 企业架构成熟度模型(EAMM)
查看>>
读书笔记:软件人才-管理的艺术
查看>>
ECMAscript 学习笔记(02)
查看>>
7z压缩gopath的src的批处理
查看>>
BZOJ2904
查看>>
CF576E
查看>>
【转载】计算机程序的思维逻辑 (5) - 小数计算为什么会出错?
查看>>
12、第七 - 网络编程基础 - 线程中的信号量(Semaphore)
查看>>
Linux Mysql 自动备份
查看>>
[转]MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXXXX'(111) 的问题
查看>>
[基础] 常见分布
查看>>