【CF472G】Design Tutorial 压位

题目大意

  给出两个\(01\)序列\(A\)和\(B\)

  汉明距离定义为两个长度相同的序列中,有多少个对应位置上的数字不一样

  \(00111\) 和 \(10101\)的距离为\(2\)

  \(Q\)次询问,每次询问给出\(p_1,p_2,len\)

  求\(a_{p_1},a_{p_1+1}\ldots a_{p_1+len?1}\)和\(b_{p_1},b_{p_1+1}\ldots b_{p_1+len?1}\)两个子串的汉明距离

  \(n\leq 2\times{10}^5,q\leq 4\times {10}^5\)

题解

  wys【挑战】弱化版

  暴力碾分块系列

  把\(a_x\ldots a_{x+63}\)压成一个\(64\)位整数,每次暴力统计。

  时间复杂度:\(O(\frac{nq}{64})\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
char s1[200010];
char s2[200010];
ull a[200010];
ull b[200010];
int cnt[100010];
int count(ull x)
{
    return cnt[x&0xffff]+cnt[(x>>16)&0xffff]+cnt[(x>>32)&0xffff]+cnt[(x>>48)&0xffff];
}
int main()
{
    int n,m,q;
    scanf("%s%s%d",s1+1,s2+1,&q);
    n=strlen(s1+1);
    m=strlen(s2+1);
    int i;
    for(i=n;i>=1;i--)
        a[i]=(a[i+1]>>1)|(s1[i]==‘1‘?(1ll<<63):0);
    for(i=m;i>=1;i--)
        b[i]=(b[i+1]>>1)|(s2[i]==‘1‘?(1ll<<63):0);
    cnt[0]=0;
    for(i=1;i<(1<<16);i++)
        cnt[i]=cnt[i>>1]+(i&1);
    int x,y,l;
    for(i=1;i<=q;i++)
    {
        scanf("%d%d%d",&x,&y,&l);
        x++;
        y++;
        int ans=0;
        while(l>=64)
        {
            ans+=count(a[x]^b[y]);
            x+=64;
            y+=64;
            l-=64;
        }
        if(l)
            ans+=count((a[x]^b[y])>>(64-l));
        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ywwyww/p/8511318.html

时间: 2024-11-09 02:53:07

【CF472G】Design Tutorial 压位的相关文章

高精度模板2(带符号压位加减乘除开方封包)

原来的那个模板:http://www.cnblogs.com/iwtwiioi/p/3991331.html 估计已经不用了. 现在我重新封包好了一个,一定很好用QAQ 加减乘除带开方带压位带重载运算符 注意一下符号即可,一定写的时候要手推四种情况!! 然后在重载<的时候,一定要注意同时判断!!!!要不然又错.. struct big { typedef ll INT; static const INT S=100000000; static const int S_n=9; static co

codevs 3119 高精度练习之大整数开根 (各种高精+压位)

/* codevs 3119 高精度练习之大整数开根 (各种高精+压位) 二分答案 然后高精判重 打了一个多小时..... 最后还超时了...压位就好了 测试点#1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms 测试点#3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#4.in 结果:AC 内存使用量: 256kB 时间使用量: 10ms 测试点#5.in 结果:AC 内

【原创】高精度(压位储存)模板

无聊写了个高精度模板玩玩...... 1 /* 2 高精度(压位储存) 3 */ 4 #include <cstdlib> 5 #include <iostream> 6 #include <cstdio> 7 #include <cstring> 8 #include <cmath> 9 const int MAX=10005;//最长长度 10 using namespace std; 11 //高精度结构体,先声明后实现 12 struct

高精度——压位的思想及应用

本文作者frankchenfu,blogs网址http://www.cnblogs.com/frankchenfu/,转载请保留此文字. 这里我们简单介绍一下高精度的计算. 我们都知道在Cpp/C/Pas等语言中,整数最大能储存\(2^{64} -1\),超过这个范围就表示不了了(不包括个别支持int128的编译器).这个时候,我们如果希望把这些整数存储下来,就需要用到高精度的算法和思想.高精度就是像小学学过的竖式运算一样的(除法除外).然后就直接模拟即可.除法一位一位地试商即可. 接下来我们发

[BZOJ4942][NOI2017]整数(线段树+压位)

CCF的题经常是对于一个不是非常高级的算法或数据结构挖掘性质进行优化. 松爷的题总是充满常数优化气息,这个题也确实是在常数上做文章. 首先如果全加的话是可以直接暴力的,因为可以证明对每一位来说是均摊$O(1)$的,将a二进制分解一次. 然后将暴力想下去之后容易发现,二进制加法如果进位,肯定是找到这一位之前第一个为0的位加一,然后这两位之间的所有位都变成0(就是模拟竖式加法),减法反之. 于是这个东西就是前驱查找和区间修改,应用线段树解决,$O(n\log^{2}n)$. 但是看到极其相近的数据范

压位高精

压位高精:即通过将原来数组中一个位置存一位数,改为一个位置存p位数(8-10).本质上是一种利用进制转换思想的压缩方式. 压位高精VS普通高精优势: 1.节省空间.(10倍以上) 2.节省时间(循环次数少)(10倍) 3.在对于高精与低精(乘法不超int)运算时,可以利用进制较高的优势,达到简化代码量的目的.(不需要频繁进位) 例题:洛谷 P3223 组合数学+高精乘低精. #include<cstdio> #include<algorithm> #include<iostr

[SDOI2009]SuperGCD 【压位高精度+辗转相减】

题目链接: https://www.luogu.org/problemnew/show/P2152 题目概述:  计算两个大整数(A,B)的最大公因数 数据范围 0 < A , B ≤ 10 ^ 其一在于辗转相减法--辗转相除法的优化(针对大数,避免了大数的模运算带来的多方面的复杂度) 思想就是 以数次 A-B  代替 A%B (这二者是等价的) 辗转相减法: 1 /* 2 Write(X) 输出X 3 Down(X) X除以2 4 Up(X) X乘以2 5 */ 6 void Solve(){

线段树(压位)luogu P1558色板游戏

题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, ... L. 现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事: "C A B C" 指在A到 B 号方格中涂上颜色 C. "P A B" 指老师的提问:A到 B号方格中有几种颜色. 学校的颜料盒中一共有 T 种颜料.为简便起见,我们把他们标记为 1, 2, ... T. 开始时色板上原

高精度压位

压位的原因 正常的高精度计算中,每一位只存了一位数字,可是当面对比较大的计算的时候呢,如果说每一位都只存一位数字,那么计算的时间就会比较地长.这个时候可以通过每一位高精度中存储多位数字的方法来降低运算的时间 例题引入 简单的来说就是 一个高精度的开根号,只要求开到整数向下取整就可以了.数据范围是10^1000; 首先就是开高精度根号的方法,很容易想到的方法就是二分或者是手动开根号.我这里使用的是二分的方法. 这一道题最开始我是直接高精度来的,然后TLE了,接着我压了四位,还是TLE了,然后直接1