Codeforces Round #470

A. Protect Sheep 

题解:如果W与S不相邻,就在W的上下左右放上D。注意不能让D覆盖了W,如:WWD

 1 /*
 2 * Author:  Plumrain
 3 * Created Time:  2013-11-11 15:38
 4 * File Name: DP-CF-148D.cpp
 5 */
 6 #pragma warning(disable:4996)
 7 #include <iostream>
 8 #include <cstdio>
 9 #include <cstring>
10 using namespace std;
11 
12 const int maxn = 100005;
13 
14 int n, m;
15 char map[505][505];
16 int dx[] = { 0,1,0,-1 }, dy[] = { 1,0,-1,0 };
17 
18 int main()
19 {
20     while (scanf("%d%d", &n, &m) != EOF) {
21         memset(map, 0, sizeof(map));
22         for (int i = 0; i < n; i++) scanf("%s", map[i]);
23         bool flag = true;
24         for (int i = 0; i < n; i++) {
25             for (int j = 0; j < m; j++) {
26                 if (map[i][j] == 'W') {
27                     for (int k = 0; k < 4; k++) {
28                         int mx = dx[k] + i, my = dy[k] + j;
29                         if (mx < 0 || mx >= n || my < 0 || my >= m || map[mx][my] == 'W') continue;
30                         if (map[mx][my] == 'S') { flag = false; break; }
31                         map[mx][my] = 'D';
32                     }
33                 }
34                 if (!flag) break;
35             }
36             if (!flag) break;
37         }
38         if (!flag) cout << "No" << endl;
39         else {
40             cout << "Yes" << endl;
41             for (int i = 0; i <= n; i++) printf("%s
", map[i]);
42         }
43     }
44 }

B. Primal Sport

 1 #pragma warning(disable:4996)
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 1e6 + 10;
 9 
10 int n, ans;
11 int p[maxn];
12 
13 int main()
14 {
15     while (scanf("%d", &n) != EOF) {
16         ans = n;
17         for (int i = 2; i <= n; i++) {
18             if (!p[i]) for (int j = 2 * i; j <= n; j += i) p[j] = i;
19             p[i] = i - p[i] + 1;
20         }
21         for (int i = p[n]; i <= n; i++) ans = min(ans, p[i]);
22         printf("%d
", ans);
23     }
24     return 0;
25 }

C. Producing Snow

题解:构造这样一个数列

还有一种是用二分查找pile消失在哪一天。

 1 #pragma warning(disable:4996)
 2 #include <iostream>
 3 #include <queue>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long ll;
 9 
10 const int maxn = 1e5 + 5;
11 
12 int n, a[maxn];
13 
14 priority_queue<ll, vector<ll>, greater<ll> > q;
15 
16 int main()
17 {
18     while (scanf("%d", &n) != EOF) {
19         while (!q.empty()) q.pop();
20         for (int i = 1; i <= n; i++) scanf("%I64d", a + i);
21         ll sum = 0, ans = 0, x;
22         for (int i = 1; i <= n; i++) {
23             scanf("%lld", &x);
24             q.push((ll)a[i] + sum);
25             while (q.top() <= sum + x && !q.empty()) { ans += (q.top() - sum); q.pop(); }
26             ans += (ll)q.size()*x;
27             sum += x;
28             printf("%I64d
", ans);
29             ans = 0;
30         }
31     }
32     return 0;
33 }

 二分查找+树状数组

 1 #pragma warning(disable:4996)
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 
 9 const int maxn = 1e5 + 5;
10 
11 int n, a[maxn], b[maxn], bit[maxn];
12 ll sum[maxn], ans[maxn];
13 
14 void Update(int i, int x) {
15     while (i <= n) {
16         bit[i] += x;
17         i += i & -i;
18     }
19 }
20 
21 int Query(int i) {
22     int s = 0;
23     while (i > 0) {
24         s += bit[i];
25         i -= i & -i;
26     }
27     return s;
28 }
29 
30 int main()
31 {    
32     while (scanf("%d", &n) != EOF) {
33         sum[0] = 0;
34         memset(bit, 0, sizeof(bit));
35         memset(ans, 0, sizeof(ans));
36         for (int i = 1; i <= n; i++) scanf("%d", a + i);
37         for (int i = 1; i <= n; i++) {
38             scanf("%d", b + i);
39             sum[i] = sum[i - 1] + b[i];
40         }
41         for (int i = 1; i <= n; i++) {
42             int p = lower_bound(sum + i, sum + n + 1, a[i] + sum[i - 1]) - (sum);
43             if (p > n) p = n;
44             if (i < p) {
45                 Update(i, 1);
46                 Update(p,-1);
47             }
48             if (i <= p) {
49                 if (a[i] + sum[i - 1] > sum[p]) ans[p] += b[p];
50                 else ans[p] += (a[i] - sum[p - 1] + sum[i - 1]);
51             }
52         }
53         for (int i = 1; i <= n; i++) {
54             ans[i] += 1LL * b[i] * Query(i);
55             printf("%I64d%c", ans[i], i == n ? '
' : ' ');
56         }
57     }
58     return 0;
59 }

 D. Perfect Security

Alice has a very important message M consisting of some non-negative integers that she wants to keep secret from Eve. Alice knows that the only theoretically secure cipher is one-time pad. Alice generates a random key K of the length equal to the message's length. Alice computes the bitwise xor of each element of the message and the key (, where denotes the bitwise XOR operation) and stores this encrypted message A. Alice is smart. Be like Alice.

For example, Alice may have wanted to store a message M = (0, 15, 9, 18). She generated a key K = (16, 7, 6, 3). The encrypted message is thus A = (16, 8, 15, 17).

Alice realised that she cannot store the key with the encrypted message. Alice sent her key K to Bob and deleted her own copy. Alice is smart. Really, be like Alice.

Bob realised that the encrypted message is only secure as long as the key is secret. Bob thus randomly permuted the key before storing it. Bob thinks that this way, even if Eve gets both the encrypted message and the key, she will not be able to read the message. Bob is not smart. Don't be like Bob.

In the above example, Bob may have, for instance, selected a permutation (3, 4, 1, 2) and stored the permuted key P = (6, 3, 16, 7).

One year has passed and Alice wants to decrypt her message. Only now Bob has realised that this is impossible. As he has permuted the key randomly, the message is lost forever. Did we mention that Bob isn't smart?

Bob wants to salvage at least some information from the message. Since he is not so smart, he asks for your help. You know the encrypted message A and the permuted key P. What is the lexicographically smallest message that could have resulted in the given encrypted text?

More precisely, for given A and P, find the lexicographically smallest message O, for which there exists a permutation π such that for every i.

Note that the sequence S is lexicographically smaller than the sequence T, if there is an index i such that Si < Ti and for all j < i the condition Sj = Tj holds.

Input

The first line contains a single integer N (1 ≤ N ≤ 300000), the length of the message.

The second line contains N integers A1, A2, ..., AN (0 ≤ Ai < 230) representing the encrypted message.

The third line contains N integers P1, P2, ..., PN (0 ≤ Pi < 230) representing the permuted encryption key.

Output

Output a single line with N integers, the lexicographically smallest possible message O. Note that all its elements should be non-negative.

Examples
Input
Copy
3
8 4 13
17 2 7
Output
10 3 28
Input
Copy
5
12 7 87 22 11
18 39 9 12 16
Output
0 14 69 6 44
Input
Copy
10
331415699 278745619 998190004 423175621 42983144 166555524 843586353 802130100 337889448 685310951
226011312 266003835 342809544 504667531 529814910 684873393 817026985 844010788 993949858 1031395667
Output
128965467 243912600 4281110 112029883 223689619 76924724 429589 119397893 613490433 362863284
Note

In the first case, the solution is (10, 3, 28), since , and . Other possible permutations of key yield messages (25, 6, 10), (25, 3, 15), (10, 21, 10), (15, 21, 15) and (15, 6, 28), which are all lexicographically larger than the solution.

题意:A数组和P数组异或后得到新的序列的字典序要最小,注意P数组中的每一个数只能用一次。

题解:很长的题目啊~~~这里需要转一个弯,为了字典序最小,则 a[ i ] 每次异或得到的值就要最小,所以就用上了01字典树。

 1 #pragma warning(disable:4996)
 2 #include<cstdio>
 3 #include<bitset>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 const int N = 33;
10 const int maxn = 300005;
11 
12 struct node {
13     int num,t;            // t 是为了计数,当t=0时说明这个节点已经被删除了!!!!!!!!! 
14     node* next[2];
15     node() {
16         t = num = 0;
17         memset(next, 0, sizeof(next));
18     }
19 };
20 
21 node* root = NULL;
22 
23 void Build(int n) {
24     bitset<N> bit = n;
25     node* rt = root;
26     for (int i = 32; i >= 0; i--) {
27         int id = bit[i];
28         if (!rt->next[id]) {
29             node* tem = new node();
30             rt->next[id] = tem;
31             rt = tem;
32         }
33         else rt = rt->next[id];
34         rt->t ++;
35     }
36     rt->num = n;
37 }
38 
39 int Query(int m) {
40     bitset<N> bit = m;
41     node* rt = root;
42     for (int i = 32; i >= 0; i--) {
43         int id = bit[i];
44         if (rt->next[id] && rt->next[id]->t != 0) {
45             rt = rt->next[id];
46             rt->t--;
47         }
48         else {
49             rt = rt->next[id ^ 1];
50             rt->t--;
51         }
52     }
53     return rt->num;
54 }
55 
56 void del(node* root) {
57     for (int i = 0; i < 2; i++) if (root->next[i]) del(root->next[i]);
58     delete root;
59 }
60 
61 int a[maxn];
62 
63 int main()
64 {
65     int n;
66     while (scanf("%d", &n) != EOF) {
67         root = new node();
68         for (int i = 1; i <= n; i++) scanf("%d", a + i);
69         for (int i = 1; i <= n; i++) {
70             int temp;
71             scanf("%d", &temp);
72             Build(temp);
73         }
74         for (int i = 1; i <= n; i++) printf("%d
", a[i] ^ (Query(a[i])));
75         del(root);             //一定要删除整棵树啊,因为是new出来的
76     }
77     return 0;
78 }
原文地址:https://www.cnblogs.com/zgglj-com/p/8562315.html