ZOJ Monthly, June 2018 Solution

A - Peer Reviewnode

Water.c++

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t, n;
 5 
 6 int main()
 7 {
 8     scanf("%d", &t);
 9     while (t--)
10     {
11         scanf("%d", &n);
12         for (int i = 1; i <= n; ++i) printf("0%c", " \n"[i == n]);
13     }
14     return 0;
15 }
View Code

 

 

B - Boring Gameide

Unsolved. spa

C - Enigma Machine3d

Unsolved.code

 

D - Number Theoryblog

Unsolved.排序

 

E - Chasingit

Solved.io

題意:兩我的在一個二維平面上,剛開始兩我的在第二象限或者第三象限,A跑到Y軸B就不能追了,B的速度是A的K倍,求B可否追到B

思路:k < 0 那麼必然不行

k == 0 判斷是否是在同一高度,若是是判斷起始位置

k > 0  假設y軸上存在某個點 使得A B 可以在該點相遇,列方程求解

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 double xa, xb, ya, yb, k;
 6 
 7 int main()
 8 {
 9     int t;
10     scanf("%d", &t);
11     while(t--)
12     {
13         scanf("%lf %lf %lf %lf %lf", &xa, &ya, &xb, &yb, &k);
14         if(k < 1.0)
15         {
16             puts("N");
17         }
18         else if(k == 1.0)
19         {
20             if(ya != yb) puts("N");
21             else if(xb < xa) puts("N");
22             else puts("Y");
23         }
24         else
25         {
26             double a = k * k - 1.0;
27             double b = -2.0 * k * k * ya + 2.0 * yb;
28             double c = k * k * xa * xa - xb * xb + k * k * ya * ya - yb * yb;
29             double d = b * b - 4.0 * a * c;
30             if(d >= 0) puts("N");
31             else puts("Y");
32         }
33     }    
34     return 0;
35 }
View Code

 

F - Carrot Gathering

Unsolved.

 

G - Virtual Singers

Upsolved.

題意:

 

H - How Many Palindromes

Unsolved.

 題意:

有$n個A數和m個B數 m <= n,對每一個B數都匹配一個A數,使得\sum_{i = 1}^{i = m} |B[i] - A[i]| 最小$

思路:

考慮費用流的思想,維護三個堆

將$A、B 數放在一塊兒排序,而後從左往右枚舉$

$若是當前數是A$

  若是左邊有未匹配的$B_1數,那麼與之匹配便可,此操做不用考慮反悔操做$

  $由於假若有另外一個B_2,使得B_2 與 這個A匹配更優$

  那麼後面必然要有另外一個$A_2 來匹配這個B_1 $

  $貢獻是 A_2 - B_1 + B_2 - A_1 這個式子顯然小於 A_2 - B_2 + A_1 - B_1$

  由於這四個數字存在大小關係

  $A_2 - B_1 大於 A_2 - B_2 + A_1 - B_1$

  若是左邊沒有未匹配的$B_1數,那麼考慮B的反悔操做是否更優$

  $更優的話就反悔而且將代價取反並算上A往右匹配的貢獻放入堆Q_A中, 至關於反悔操做$

$若是當前數是B$

  $若是左邊有未匹配的A數,那麼與之匹配,而且將代價取反而且算上B往右匹配的貢獻放入堆Q_C中$

  不然放入堆$Q_B$中表示還未匹配

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 100010
 6 int t, n, m; ll x;
 7 struct node 
 8 {
 9     ll v; int Type;
10     node () {}
11     node (ll v, int Type) : v(v), Type(Type) {}
12     bool operator < (const node &r) const { return v < r.v; }   
13 }arr[N << 1];
14 priority_queue <ll, vector <ll> , greater <ll> > A, B, C;  
15 
16 int main()
17 {
18     scanf("%d", &t);
19     while (t--)
20     {
21         while (!A.empty()) A.pop();
22         while (!B.empty()) B.pop();
23         while (!C.empty()) C.pop();
24         scanf("%d%d", &n, &m);
25         for (int i = 1; i <= n; ++i) 
26         {
27             scanf("%lld", &x);
28             arr[i] = node(x, 0);
29         }
30         for (int i = 1; i <= m; ++i)
31         {
32             scanf("%lld", &x);
33             arr[n + i] = node(x, 1);
34         }
35         sort(arr + 1, arr + 1 + n + m);
36         ll res = 0;
37         for (int i = 1; i <= n + m; ++i)
38         {
39             if (arr[i].Type == 1)
40             {
41                 if (!A.empty())
42                 {
43                     x = A.top(); A.pop();
44                     res += arr[i].v + x;
45                     C.push(-x - 2 * arr[i].v);
46                 }
47                 else 
48                     B.push(-arr[i].v); 
49             }
50             else
51             {
52                 if (!B.empty())
53                 {
54                     x = B.top(); B.pop();
55                     res += arr[i].v + x;
56                 }
57                 else if (!C.empty()) 
58                 {
59                     x = C.top(); 
60                     if (arr[i].v + x < 0)
61                     {
62                         C.pop();
63                         res += arr[i].v + x;
64                         A.push(-x - 2 * arr[i].v);
65                     }
66                     else 
67                         A.push(-arr[i].v);
68                 }
69                 else
70                     A.push(-arr[i].v); 
71             }
72         }
73         printf("%lld\n", res);
74     }
75     return 0;
76 }
View Code

 

 

I - District Division

Solved.

題意:給出一棵樹,求能不能分紅$\frac{n}{k}$ 個連通塊,使得每塊個數爲k

思路:若是存在合法分法,那麼必然存在某個子樹大小爲k,DFS下去,再回溯上來判斷便可,遇到大小爲k的子樹就分塊

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e5 + 10;
 6 
 7 int n, k;
 8 
 9 int val[maxn];
10 int fa[maxn];
11 int vis[maxn];
12 int cnt;
13 vector<int>root;
14 vector<int>G[maxn];
15 
16 void Init()
17 {
18     cnt = 0;
19     root.clear();
20     for(int i = 1; i <= n; ++i)
21     {
22         val[i] = vis[i] = 0;
23         fa[i] = i;
24         G[i].clear();
25     }    
26 }
27 
28 void DFS(int u, int pre)
29 {
30     val[u] = 1;
31     fa[u] = pre;
32     for(int i = 0, len = G[u].size(); i < len; ++i)
33     {
34         int v = G[u][i];
35         if(v == pre) continue;
36         DFS(v, u);
37         val[u] += val[v];
38     }
39     if(val[u] == k)
40     {
41         cnt++;
42         val[u] = 0;
43         root.push_back(u);
44     }
45 }
46 
47 void DFS2(int u, int pre)
48 {
49     if(vis[u]) return ;
50     vis[u] = 1;
51     printf("%d%c", u, " \n"[cnt == k]);
52     cnt++;
53     for(int i = 0, len = G[u].size(); i < len; ++i)
54     {
55         int v = G[u][i];
56         if(v == pre) continue;
57         DFS2(v, u);
58     }
59 }
60 
61 int main()
62 {
63     int t;
64     scanf("%d", &t);
65     while(t--)
66     {
67         scanf("%d %d", &n, &k);
68         Init();
69         for(int i = 1; i < n; ++i)
70         {
71             int u, v;
72             scanf("%d %d", &u, &v);
73             G[u].push_back(v);
74             G[v].push_back(u);
75         }
76         DFS(1, -1);
77         if(cnt != n / k)
78         {
79             puts("NO");
80             continue;
81         }
82         puts("YES");
83         for(int i = 0, len = root.size(); i < len; ++i)
84         {
85             cnt = 1;
86             DFS2(root[i], fa[root[i]]);
87         }
88     }    
89     return 0;
90 }
View Code

 

J - Good Permutation

Solved.

題意:每次可以交換相鄰兩個數,求最少交換次數使得知足題目給出的序列條件

思路:經過枚舉每次在第一位的數,從而遞推下一種狀態,好比12345推出51234即加上5移到第一位的步數再減去5帶來的貢獻

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const int maxn = 1e5 + 10;
 8 
 9 int n;
10 int arr[maxn];
11 int pos[maxn];
12 int a[maxn];
13 
14 int lowbit(int p)
15 {
16     return p & (-p);
17 }
18 
19 void update(int p)
20 {
21     while(p <= n)
22     {
23         a[p]++;
24         p += lowbit(p);
25     }
26 }
27 
28 int query(int p)
29 {
30     int res = 0;
31     while(p)
32     {
33         res += a[p];
34         p -= lowbit(p);
35     }
36     return res;
37 }
38 
39 int main()
40 {
41     int t;
42     scanf("%d", &t);
43     while(t--)
44     {
45         scanf("%d", &n);
46         ll ans = 0;
47         for(int i = 1; i <= n; ++i) a[i] = 0;
48         for(int i = 1; i <= n; ++i)
49         {
50             scanf("%d", arr + i);
51             pos[arr[i]] = i;
52         }
53         for(int i = n; i >= 1; --i)
54         {
55             ans += query(arr[i] - 1);
56             update(arr[i]);
57         }
58         ll tmp = ans;
59         for(int i = 1; i <= n; ++i)
60         {
61             tmp = tmp + n - pos[i] - (pos[i] - 1);
62             ans = min(ans, tmp);
63         }
64         printf("%lld\n", ans);
65     }
66     return 0;
67 }
View Code
相關文章
相關標籤/搜索