CodeForces Round #296 Div.2

A. Playing with Paper

如果a是b的整数倍,那么将得到a/b个正方形,否则的话还会另外得到一个(b, a%b)的长方形。

时间复杂度和欧几里得算法一样。

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 
 5 //const int maxn = ;
 6 
 7 int main()
 8 {
 9     //freopen("in.txt", "r", stdin);
10 
11     long long a, b, ans = 0;
12     scanf("%I64d%I64d", &a, &b);
13     while(a % b != 0)
14     {
15         ans += a / b;
16         long long ta = b;
17         long long tb = a % b;
18         a = ta; b = tb;
19     }
20     ans += a / b;
21     printf("%I64d
", ans);
22 
23     return 0;
24 }
代码君

B. Error Correct System

代码略矬。。

贪心,建一个有向图G[a][b] = i,代表第i个字符“想”从字母a变成字母b,也就是说s1[i] == a, s2[i] == b,如果s1中第i个字母从a变成b后,题中定义的那个Hamming distance就会减小1.如果有G[a][b] 和 G[b][a]的话,直接将这两个字符交换就好了,Hamming distance一共减少2。

否则,退而求其次,交换一下只满足G[a][b] G[b][c]的两个位置的字符,这样Hamming distance减小1.

再否则,,,直接输出-1 -1

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 
 5 const int maxn = 200000 + 10;
 6 
 7 int n;
 8 char s1[maxn], s2[maxn];
 9 
10 int G[30][30];
11 
12 int main()
13 {
14     //freopen("in.txt", "r", stdin);
15 
16     scanf("%d", &n); getchar();
17     gets(s1+1); gets(s2+1);
18 
19     int ans = 0, p1 = -1, p2 = -1;
20     for(int i = 1; i <= n; i++) if(s1[i] != s2[i]) ans++;
21 
22     for(int i = 1; i <= n; i++) if(s1[i] != s2[i])
23     {
24         int x = s1[i]-'a', y = s2[i]-'a';
25         G[x][y] = i;
26         if(G[y][x]) { p1 = i; p2 = G[y][x]; ans -= 2; break; }
27     }
28 
29     bool flag = false;
30     if(p1 + p2 == -2)
31     {
32         for(int i = 0; i < 26; i++)
33         {
34             for(int j = 0; j < 26; j++) if(G[i][j])
35             {
36                 for(int k = 0; k < 26; k++) if(G[j][k])
37                 {
38                     flag = true;
39                     ans--;
40                     p1 = G[i][j]; p2 = G[j][k];
41                     break;
42                 }
43                 if(flag) break;
44             }
45             if(flag) break;
46         }
47     }
48 
49     printf("%d
%d %d
", ans, p1, p2);
50 
51     return 0;
52 }
代码君

C. Glass Carving

果然,熟练使用STL是很有必要的,减小编码复杂度,速度上也不会太慢。

话说有一个人对着一块玻璃横着或者竖着切来切去。

每次切完都要询问一下最大的一块玻璃的面积是多少。

将所有切割的位置放在一个集合中,还有所有相邻位置之间的距离放在一个多重集合里面。

每一次切割位置x,都将a<x<b这个区间分成了两个,同时将x加入到对应的切割位置集合;然后更新一下距离集合,具体就是删除b-a这段距离(如果有多个,只要删除一个就好了),然后分别插入(x-a) 和 (b-x)这两段被分隔开的距离。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     //freopen("in.txt", "r", stdin);
 7 
 8     set<int> sh, sv;
 9     multiset<int> mh, mv;
10     set<int>::iterator l, r;
11 
12     int w, h, n;
13     scanf("%d%d%d", &w, &h, &n); getchar();
14     sh.insert(0); sh.insert(h);
15     sv.insert(0); sv.insert(w);
16     mh.insert(h); mv.insert(w);
17 
18     while(n--)
19     {
20         char op; int cut;
21         scanf("%c %d", &op, &cut); getchar();
22         if(op == 'H')
23         {
24             l = sh.lower_bound(cut);
25             r = l; l--;
26             sh.insert(cut);
27             mh.insert(cut-(*l));
28             mh.insert((*r)-cut);
29             mh.erase(mh.find((*r) - (*l)));
30         }
31         else
32         {
33             l = sv.lower_bound(cut);
34             r = l; l--;
35             sv.insert(cut);
36             mv.insert(cut - (*l));
37             mv.insert((*r) - cut);
38             mv.erase(mv.find((*r) - (*l)));
39         }
40 
41         printf("%I64d
", (long long)(*mh.rbegin()) * (*mv.rbegin()));
42     }
43 
44     return 0;
45 }
代码君

最后再说一点题外话:这次是只要删除multiset中一个元素,只要S.erase(S.find(val))就行了。

如果我们想要删除所有multiset中值为val的元素该怎么办?

有一个equal_range的成员函数,调用S.equal_range(val)就会返回一个pair<multiset::iterator, multiset::iterator>类型的值ret,它代表了一个区间,这个区间中就包含了multiset中所有值为val的元素。最后删除的时候,直接S.erase(ret.first, ret.second)

下面是http://www.cplusplus.com/reference/set/multiset/equal_range/ 中的实例:

 1 // multiset::equal_elements
 2 #include <iostream>
 3 #include <set>
 4 
 5 typedef std::multiset<int>::iterator It;  // aliasing the iterator type used
 6 
 7 int main ()
 8 {
 9   int myints[]= {77,30,16,2,30,30};
10   std::multiset<int> mymultiset (myints, myints+6);  // 2 16 30 30 30 77
11 
12   std::pair<It,It> ret = mymultiset.equal_range(30); //      ^        ^
13 
14   mymultiset.erase(ret.first,ret.second);
15 
16   std::cout << "mymultiset contains:";
17   for (It it=mymultiset.begin(); it!=mymultiset.end(); ++it)
18     std::cout << ' ' << *it;
19   std::cout << '
';
20 
21   return 0;
22 }
代码君
原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4346143.html