【题解】Recover the String Codeforces 708B

题解讲的不是很详细,有些定理未加证明地直接给出,需要读者自己思考,如有不懂欢迎在讨论区提问

由00和11的个数可以确定0和1的个数
假设00的个数是b,必须满足a*(a-1)/2=b,且a是整数
这时候,a便是0的个数,求1的个数同理
同时,01和10的个数的和 一定是 0的个数*1的个数
然后构造一个00000000001111111111这样的串,是不存在10这样的子序列的
我们称最右边的一坨1叫“没有交换的1”,然后每次选择这里面最左边的一个1和第x(x待确定)个0交换
注意到,和第x个0交换之后,产生的10的个数是数字1跨过的0的个数
真的是这样么?
对于这样的一个串0000011111,我们假设第一步是第一个1和第二个0交换,跨过了4个0
变成0100001111,这时候,我们执行第二步
发现“没有交换的1”中,最左边的1和第2,3,4,5个0交换的时候,满足上面的定律
但是和第一个0交换,就不满足了,因为跨过了一个1
于是我们想让交换不跨过1,即满足,每次交换到第x个0,这个x是非降的
于是每次交换就尽量和左边的0交换,并累计产生的10的数量,根据上面的分析,很容易确定到底和第几个0交换
问题就变成了“查询第x个0的位置”
平衡树

以上是我的智障做法,然后zrf大神教我做人:
前提是满足00,11,10,01的个数限制,就是上面讨论到的那套基本法
从左到右依次放0或者1,保存还有多少个0没有放
假如还有x个0没有放,那么我们放一个1,产生的10的个数就是x
在不超过10的个数的限制下尽量把1放在前面,贪心
线性

等等!还没完!在我WA了几遍之后,发现要特殊处理a00 == 0和a11 == 0的情况
注意到a00 == 0的时候,最终的答案可以有一个0,也可以没有0
这时候到底有没有0取决于a10和a01的数量
即,当a10 == 0 && a01 == 0 && a00 == 0的时候,没有0
当a10 != 0 && a01 != 0 && a00 == 0的时候,有一个0
对于数字1也是一样,讨论一下就好了

为什么我如此智障呢?我被数据范围坑了
按照数据范围,数字最多有90000个,于是我就想O(nlogn)
线性做法一开始想到了,后来觉得Div1B不可能这么naive。。。就弃了

下面贴代码,没有注释,不过应该比较好懂吧。。。不懂的欢迎在讨论区提问

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <cstdlib>
 7
 8 using namespace std;
 9
10 int a00, a01, a10, a11;
11 int a0, a1, n;
12
13 void quit() {
14     cout << "Impossible" << endl; exit(0);
15 }
16
17 int main() {
18     cin >> a00 >> a01 >> a10 >> a11;
19     a0 = sqrt(a00<<1)+1; a1 = sqrt(a11<<1)+1;
20     if( a01+a10+a11 == 0 ) a1 = 0;
21     if( a01+a10+a00 == 0 ) a0 = 0;
22     if( a0*(a0-1)/2 != a00 || a1*(a1-1)/2 != a11 ) quit();
23     if( a01+a10 != a0*a1 ) quit();
24     n = a0+a1;
25     for( int i = 0; i < n; ++i ) {
26         if( a10 >= a0 ) cout << 1, a10 -= a0;
27         else cout << 0, --a0;
28     }
29     if( !n ) cout << 0;
30     return 0;
31 }
时间: 2024-12-26 23:29:13

【题解】Recover the String Codeforces 708B的相关文章

UVA - 10559 Blocks 和 Vasya and Binary String CodeForces - 1107E (dp OR 记忆化搜索)

UVA - 10559 Blocks 题意:消消乐,每次连续相同的可以消除,分数加上长度的平方,问最多可以获得几分全部消完 题解: 区间dp + 记忆化搜索 dp[i][j][k] : (区间 [i,  j] 后面带上一段和 j 颜色相同的且长度为 k )的消消乐最大积分 1.消最后一段颜色和 j 颜色相同的 dp[i][j][k] <-- dp[i][j-1][0] + (k+1)^2 2.对于i <= l < j, 如果 l 和 j 的颜色相同, 那么可以把 [l+1, j-1]消掉

CodeForces 708B Recover the String

构造. 根据$a[0][0]$可以求得$0$的个数$p$,根据$a[1][1]$可以求得$1$的个数$q$. 如果找不到$p$或$q$,那么就无解. 每一个$0$放到序列中的任何一个位置,假设和前面的$1$产生了$x$对$10$,和后面的$1$产生了$y$对$01$,那么$x+y$一定等于$q$. 也就是说如果$p*q$不等于$a[0][1]+a[1][0]$,那么就无解了.否则只要将$1$一个一个放进序列中,凑成$1$前面的$0$的个数总和是$a[0][1]$就可以了. 上面的方法对一般的情况

D. Mahmoud and Ehab and the binary string Codeforces Round #435 (Div. 2)

http://codeforces.com/contest/862/problem/D 询问题 fflush(stdout) 调试: 先行给出结果,函数代替输入 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <time.h> 6 #include <string> 7 #include <se

leetCode题解之寻找string中最后一个word的长度

1.题目描述 返回一个 string中最后一个单词的长度.单词定义为没有空格的连续的字符,比如 'a','akkk'. 2.问题分析 从后向前扫描,如果string是以空格'  '结尾的,就不用计数,现将空格最后的空格排除掉,直到找到最后一个出现的字符.从最后一个出现的字符开始计数,一直到下一次出现空格' '. 特殊情况是 输入的字符串是空的,先排除掉. 3.代码 1 1 int lengthOfLastWord(string s) { 2 3 if(s.size() == 0) // 排除字符

LeetCode题解之Rotate String

1.题目描述 2.问题分析 直接旋转字符串A,然后做比较即可. 3.代码 1 bool rotateString(string A, string B) { 2 if( A.size() != B.size() ) 3 return false; 4 if( A.empty() && B.empty() ) 5 return true; 6 int i = 0 ; 7 while( i < A.size() ){ 8 char c = A[0] ; 9 A += c; 10 A.er

codeforces708b// Recover the String //AIM Tech Round 3 (Div. 1)

题意:有一个01组成的串,告知所有长度为2的子序列中,即00,01,10,11,的个数a,b,c,d.输出一种可能的串. 先求串中0,1的数目x,y. 首先,如果00的个数a不是0的话,设串中有x个0,C(X,2)=a,那么x*(x+1)=2a,解方程(其实只要看sqrt(x)*(sqrt(x)+1)等不等于2a),x没有整数解就IMPOSSIBLE.同理得出1的个数y.如果00个数是0看01个数. 第二,如果x*y!=b+c则IMPOSSIBLE,具体自己举个例子就明白. 最后,先将所有的0组

CF708B Recover the String 构造

For each string s consisting of characters '0' and '1' one can define four integers a00, a01, a10 and a11, where axy is the number of subsequences of length 2 of the string s equal to the sequence {x,?y}. In these problem you are given four integers

Minimal string CodeForces – 797C

题目链接 题目难度: 1700rating 题目类型:string+贪心+STL 题目思路: 由于题目要求的最终结果是字典序最小的那个字符串,那么我们从贪心的从'a'开始查找字符串里是否存在,如果存在,就先把后面的所有的该字符放在答案字符串u中(u可以用queue来表示),而字符串t可以用stack来表示.中间的字符串都加入到stack中,当一个字符全加入后,继续从小到大的查找剩余字符串中还剩的字符,并且与栈顶元素进行比较,如果小于栈顶元素,需要先输出栈顶元素.中间的细节比较多,详细看代码.我用

Balanced Ternary String CodeForces - 1102D (贪心+思维)

You are given a string ss consisting of exactly nn characters, and each character is either '0', '1' or '2'. Such strings are called ternary strings. Your task is to replace minimum number of characters in this string with other characters to obtain