AtCoder Regular Contest 088

AtCoder Regular Contest 088

C - Multiple Gift

输出$log_2\frac{y}{x}$。

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 typedef long long ll;
 5 int main() {
 6     ll a, b, res = 0;
 7     cin >> a >> b;
 8     for (b /= a; b; b >>= 1, ++res);
 9     cout << res << endl;
10     return 0;
11 }
View Code

D - Wide Flip

简要题意:有一个长度为$n(n<=10^5)$的01串,你需要找到一个最大的$k$使得在若干次操作后所有的1都能变成0。

操作:选择一段连续的区间$[l,r]$$(r - l + 1 \geqslant k)$,并把上面所有的0变成1,1变成0。

现在咱来看看怎么做这道题。

假设$s_i \neq s_{i+1}$,为了让他们相同咱可以对$[1,i]$和$[1,i+1]$或$[i,n]$和$[i+1,n]$同时进行操作,所以$ans=max\{min\{i, n-i\},s_i \neq s_{i+1}\}$

时间复杂度$O(n)$

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 char s[100010];
 6 int n, ans;
 7 int main() {
 8     scanf("%s", s + 1);
 9     ans = n = strlen(s + 1);
10     for (int i = 1; i < n; ++i)
11         if (s[i] != s[i+1])
12             ans = min(ans, max(i, n - i));
13     printf("%d\n", ans);
14     return 0;
15 }
View Code

E - Papple Sort

一句话题意:给你一个字符串,要把他变成一个回文最少需要交换字符多少次?如果无法变成回文,输出$-1$。

首先,如果出现奇数次的字符个数大于$1$,则显然无解。

对于相同的字符,咱肯定是要把他们放到左右两边,即配对。

咱可以看出来,交换相同的字符是没有意义的,所以相同字符之间这种相对的位置关系是不会变的。

比如说一个初始为$..a...a...a...a...$的字符串,只看$a$的话,最后如果能形成回文,那么最左边的$a$肯定是与最右边的$a$配对的。

所以咱可以$O(n)$的预处理出与$s_i$配对的字符所在的位置$p_i$。

用树状数组表示某个位置上的字符存在与否,初始时都为$1$。

咱从左往右每次都把$s_i$所对应的字符移到最末尾,再把树状数组上的$p_i-1$表示已经删除。这里说的末尾是不算已配对字符的字符串的末尾。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #include<iostream>
 5 #include<algorithm>
 6 #define pb push_back
 7 #define lowbit(x) ((x)&(-(x)))
 8 using namespace std;
 9 char s[200010];
10 int n, c[200010], a[200010];
11 long long ans;
12 vector < int > p[26];
13 bool check() {
14     int cnt = 0;
15     for (int i = 0; i < 26; ++i)
16         cnt += p[i].size() & 1;
17     return cnt < 2;
18 }
19 void add(int p, int x) {
20     for (; p <= n; p += lowbit(p)) c[p] += x;
21 }
22 int sum(int p) {
23     int res = 0;
24     for (; p; p -= lowbit(p)) res += c[p];
25     return res;
26 }
27 int main() {
28     scanf("%s", s + 1);
29     n = strlen(s + 1);
30     for (int i = 1; i <= n; ++i) p[s[i]-'a'].pb(i);
31     if (!check()) return puts("-1"), 0;
32     for (int i, sz, x = 0; x < 26; ++x) {
33         for (i = 0; i < (sz = p[x].size()); ++i)
34             a[p[x][i]] = p[x][sz-1-i];
35     }
36 
37 //    for (int i = 1; i <= n; ++i)
38 //        ans += sum(a[i]), add(a[i], 1);
39 //     上面下面这两种都可以。
40 //    for (int i = 1; i <= n; ++i) add(i, 1);
41 //    for (int i = 1; i <= n; ++i) {
42 //        ans += sum(n) - sum(a[i]);
43 //        add(a[i], -1);
44 //    }
45     printf("%lld\n", ans / 2);
46     return 0;    
47 }
View Code

 

posted @ 2017-12-26 21:04  p0ny  阅读(190)  评论(0编辑  收藏  举报