hdu 5694(BD String,折半递归)

 1 #include <bits/stdc++.h>
 2 #define lld I64d
 3 using namespace std;
 4 typedef long long ll;
 5 vector<ll> vec;
 6 /**
 7  *lower_bound 返回大于或等于x 位置的指针
 8  *
 9  * 思路:先预处理出对称的下标放入vector
10  *         dfs(x) 表示 1-x 中 B的个数
11  *         (1)若x正好等于vec[i], 则 B 的个数 = vec[i-1]/2 + 1; (对称性)
12  *         (2)否则, 在加上以vec[i-1]为对称左右到x的距离(x-vec[i-1])的B的个数后
13  *             再搜索 前面的
14  *
15  * */
16
17 void init(){
18     ll tmp = 1;
19     while(tmp <= (ll)1e18){
20         vec.push_back(tmp);
21         tmp = tmp * 2;
22     }
23 }
24 ll dfs(ll x){
25     if(x == 0) return 0;
26     int index = lower_bound(vec.begin(),vec.end(),x) - vec.begin();
27     if(vec[index] == x)    return x / 2 + 1;
28     ll t = x - vec[index-1];
29     return t + 1 + dfs(x - 2 * t - 1);
30 }
31 int main(){
32     int T;
33     init();
34     scanf("%d",&T);
35     while(T--){
36         ll l,r;
37         scanf("%lld%lld",&l,&r);
38         ll ans = dfs(r) - dfs(l-1);
39         printf("%lld\n",ans);
40     }
41     return 0;
42 }
43 /*B
44  *1234567 8 9
45  *BBD
46    .
47  *BBDBBDD
48       .
49  *BBDBBDD B BBDDBDD
50    |   |  .   |
51  * */
时间: 2025-01-15 15:33:54

hdu 5694(BD String,折半递归)的相关文章

hdu-5694 BD String(分治)

题目链接: BD String Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Problem Description 众所周知,度度熊喜欢的字符只有两个:B和D. 今天,它发明了一种用B和D组成字符串的规则: S(1)=B S(2)=BBD S(3)=BBDBBDD … S(n)=S(n−1)+B+reverse(flip(S(n−1)) 其中,reverse(s)指将字符

简单规律---BD String

HDU   5694 Problem Description 众所周知,度度熊喜欢的字符只有两个:B和D.今天,它发明了一种用B和D组成字符串的规则:S(1)=BS(2)=BBDS(3)=BBDBBDD…S(n)=S(n−1)+B+reverse(flip(S(n−1))其中,reverse(s)指将字符串翻转,比如reverse(BBD)=DBB,flip(s)指将字符串中的B替换为D,D替换为B,比如flip(BBD)=DDB.虽然度度熊平常只用它的电脑玩连连看,这丝毫不妨碍这台机器无与伦比

【c语言】编写一个函数reverse_string(char * string)(递归实现) 实现:将参数字符串中的字符反向排列。

/*编写一个函数reverse_string(char * string)(递归实现) 实现:将参数字符串中的字符反向排列. 要求:不能使用C函数库中的字符串操作函数.*/ #include <stdio.h> #include <assert.h> void reverse_string(char const * string) { assert( string != NULL ); if( *string != '\0' ) { string++; reverse_string

HDU 5008 Boring String Problem(西安网络赛B题)

HDU 5008 Boring String Problem 题目链接 思路:构造后缀数组,利用height的数组能预处理出每个字典序开始的前缀和有多少个(其实就是为了去除重复串),然后每次二分查找相应位置,然后在往前往后找一下sa[i]最小的 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int

编写一个函数reverse_string(char * string)(递归实现)

编写一个函数reverse_string(char * string)(递归实现) 实现:将参数字符串中的字符反向排列. 要求:不能使用C函数库中的字符串操作函数. #include<stdio.h> #include<assert.h> #include<stdlib.h> int my_strlen(const char*str) { assert(str); int count = 0; while (*str) { count++; str++; } retur

BD String

BD String Accepts: 388 Submissions: 1164 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 众所周知,度度熊喜欢的字符只有两个:B和D. 今天,它发明了一种用B和D组成字符串的规则: S(1)=BS(1)=BS(1)=B S(2)=BBDS(2)=BBDS(2)=BBD S(3)=BBDBBDDS(3)=B

hdu 5008 Boring String Problem(后缀数组)

题目链接:hdu 5008 Boring String Problem 题目大意:给定一个字符串,初始状态l,r为0,每次询问子串中字典序第l^r^v+1的子串区间,对于重复的输出下标小的. 解题思路:后缀数组,对给定字符串做后缀数组,然后根据height数组确定每个位置做为起点的子串有多少,然后二分查找确定起点位置,但是因为子串的重复的要输出下表小的,所以确定起点后还要确定字典序最小的下标. #include <cstdio> #include <cstring> #includ

1608 - Non-boring sequences(折半递归。。暂且这么叫吧)

该题给一个序列,让我们判断是不是不无聊序列(如果不明白请看样例), 我们可以将区间从大到小不断压缩来确定答案,首先要确定一个区间是否满足要求,只要看这个区间里是不是有一个只出现一次的数,受前面<唯一的雪花>一题的启发,我们可以在O(n)时间内求出当前数离他最近的与他相同的数的位置,用数组保存,那么可以在O(1)的时间快速判断,这样就将时间复杂度降到O(n^2) 但是这样还是不够的,会超时. 紫书上给出了一个很巧妙的方法,那就是在递归的时候折半枚举   , 时间复杂度变成了 T(n) = 2*T

hdu 5008 Boring String Problem(后缀自动机构造后缀树)

hdu 5008 Boring String Problem(后缀自动机构造后缀树) 题意:给出一个字符串s,然后每次询问一个k,求s的所有子串中,字典序第k小的是谁?多个解,则输出最左边的那个 解题思路:这道题应该是为后缀树量身定制的吧.只要构造出了后缀树,然后按字典序遍历就可以得出每个节点包含的子串的字典序的范围了,而且必然是个连续的区间范围.但是我不会后缀树啊..比赛的时候突然想到,后缀自动机是可以构造后缀树的,虽然以前没写过,但还是硬着头皮上吧,居然还真的让我给撸出来了.我的做法是这样的