ACM ICPC, JUST Collegiate Programming Contest (2018) Solution

A:Zero Array

题意:两种操作, 1 p v  将第p个位置的值改成v  2  查询最少的操作数使得所有数都变为0  操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能变为负数 

思路:考虑第二种操作,显然,最少的操作数肯定是不同数的个数 用map 记录,特殊注意0的存在

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 100010
 6 
 7 unordered_map <int, int> mp;
 8 
 9 int t, n, q;
10 
11 int arr[N];
12 
13 int main()
14 {
15     cin.tie(0);
16     cout.tie(0);
17     ios::sync_with_stdio(false);
18     cin >> t;
19     while (t--)
20     {
21         cin >> n >> q;
22         mp.clear();
23         for (int i = 1; i <= n; ++i)
24         {
25             cin >> arr[i];
26             mp[arr[i]]++;
27         }
28         int op, p, v;
29         while (q--)
30         {
31             cin >> op;
32             if (op == 1)
33             {
34                 cin >> p >> v;
35                 if (mp[arr[p]] == 1)
36                 {
37                     mp.erase(arr[p]);
38                 }
39                 else
40                 {
41                     mp[arr[p]]--;
42                 }
43                 mp[v]++;
44                 arr[p] = v;
45             }
46             else
47             {
48                 mp[0]++;
49                 cout << mp.size() - 1 << endl;
50             }
51         }
52     }
53     return 0;
54 }
View Code

 

B:New Assignment

题意:给出n个人,有男生有女生,每个人有权值,进行分组,一个男的可以一组,一个女的可以一组,一男一女可以一组当且仅当他们的权值的最大公约数大于1,求最少的分组数量

思路:优先让一男一女分组,让可以一起分组的男女连边,跑二分匹配或者最大流,建图的时候注意不能够直接GCD,这样常数比较大,我们分解质因数卡卡常就可以过去

二分图匹配:

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define N 10010
  6 #define M 1000010
  7 #define INF 0x3f3f3f3f
  8 
  9 vector <int> G[N];
 10 int uN, vN;
 11 int Mx[N], My[N];
 12 int dx[N], dy[N];
 13 int dis;
 14 bool used[N];
 15 
 16 inline bool SearchP()
 17 {
 18     queue <int> Q;
 19     dis = INF;
 20     memset(dx, -1, sizeof dx);
 21     memset(dy, -1, sizeof dy);
 22     for (int i = 0; i < uN; ++i)
 23         if (Mx[i] == -1)
 24         {
 25             Q.push(i);
 26             dx[i] = 0;
 27         }
 28     while (!Q.empty())
 29     {
 30         int u = Q.front();
 31         Q.pop();
 32         if (dx[u] > dis) break;
 33         int sz = G[u].size();
 34         for (int i = 0; i < sz; ++i)
 35         {
 36             int v = G[u][i];
 37             if (dy[v] == -1)
 38             {
 39                 dy[v] = dx[u] + 1;
 40                 if (My[v] == -1) dis = dy[v];
 41                 else
 42                 {
 43                     dx[My[v]] = dy[v] + 1;
 44                     Q.push(My[v]);
 45                 }
 46             }
 47         }
 48     }
 49     return dis != INF;
 50 }
 51 
 52 inline bool DFS(int u)
 53 {
 54     int sz = G[u].size();
 55     for (int i = 0; i < sz; ++i)
 56     {
 57         int v = G[u][i];
 58         if (!used[v] && dy[v] == dx[u] + 1)
 59         {
 60             used[v] = true;
 61             if (My[v] != -1 && dy[v] == dis) continue;
 62             if (My[v] == -1 || DFS(My[v]))
 63             {
 64                 My[v] = u;
 65                 Mx[u] = v;
 66                 return true;
 67             }
 68         }
 69     }
 70     return false;
 71 }
 72 
 73 inline int MaxMatch()
 74 {
 75     int res = 0; 
 76     memset(Mx, -1, sizeof Mx);
 77     memset(My, -1, sizeof My);
 78     while (SearchP())
 79     {
 80         memset(used, false, sizeof used);
 81         for (int i = 0; i < uN; ++i)
 82             if (Mx[i] == -1 && DFS(i))
 83                 res++;
 84     }
 85     return res;
 86 }
 87 
 88 int t, n;
 89 
 90 int arr[N], brr[N];
 91 
 92 vector <int> pr[M], fac[M];
 93 
 94 inline void Init()
 95 {
 96     for (int i = 2; i <= 1000000; ++i)
 97         if (pr[i].empty())
 98             for (int j = i; j <= 1000000; j += i) 
 99                 pr[j].emplace_back(i); 
100 }
101 
102 int a[N], b[N];
103 map <int, bool> mp;
104 
105 int main()
106 {
107     Init();
108     scanf("%d", &t);
109     while (t--)
110     {
111         scanf("%d", &n);
112         for (int i = 1; i <= n; ++i) scanf("%d", arr + i); 
113         uN = 0, vN = 0;
114         char c;
115         for (int i = 1; i <= n; ++i)
116         {
117             scanf(" %c", &c);
118             if (c == 'F')
119             {
120                 a[uN] = arr[i];
121                 for (int j = 0, len = pr[arr[i]].size(); j < len; ++j)
122                 {
123                     int x = pr[arr[i]][j];
124                     fac[x].emplace_back(uN); 
125                 }                
126                 G[uN].clear();                        
127                 uN++;
128             }            
129             else
130             {
131                 b[vN] = arr[i];
132                 vN++;
133             }
134         }
135         for (int i = 0; i < vN; ++i)
136         {
137             mp.clear();
138             for (int j = 0, len = pr[b[i]].size(); j < len; ++j)
139             {
140                 int x = pr[b[i]][j];
141                 for (int k = 0, lenn = fac[x].size(); k < lenn; ++k)
142                 {
143                     int id = fac[x][k];
144                     if (mp[id] == false)
145                     {
146                         mp[id] = true;
147                         G[id].emplace_back(i);     
148                     }
149                 }
150             }
151         }
152         printf("%d\n", n - MaxMatch());
153         for (int i = 0; i < uN; ++i)
154         {
155             for (int j = 0, len = pr[a[i]].size(); j < len; ++j)
156             {
157                 int x = pr[a[i]][j];
158                 fac[x].clear();
159             }
160         }
161     }
162 }
View Code

 最大流:

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int maxn = 1e4 + 10;
  6 const int INF = 0x3f3f3f3f;
  7 
  8 int n, m;
  9 
 10 struct Edge {
 11     int from;
 12     int to;
 13     int cap;
 14     int flow;
 15     inline Edge(){}
 16     inline Edge(int from, int to, int cap, int flow) :from(from), to(to), cap(cap), flow(flow) {};
 17 };
 18 
 19 
 20 map<pair<int, int>, bool>mp;
 21 vector<int>pre[1000010];
 22 vector<int>vec[1000010];
 23 int arr[maxn];
 24 int sex[maxn];
 25 vector<Edge>edge;
 26 vector<int>G[maxn];
 27 int vis[maxn];
 28 int d[maxn];
 29 int cur[maxn];
 30 int S, T;
 31 
 32 inline void init()
 33 {
 34     mp.clear();
 35     edge.clear();
 36     for (int i = 0; i <= n + 1; ++i)
 37     {
 38         G[i].clear();
 39     }
 40 }
 41 
 42 inline void addedge(int from, int to, int cap)
 43 {
 44     edge.push_back(Edge(from, to, cap, 0));
 45     edge.push_back(Edge(to, from, 0, 0));
 46     int len = edge.size();
 47     G[from].push_back(len - 2);
 48     G[to].push_back(len - 1);
 49 }
 50 
 51 inline bool BFS()
 52 {
 53     memset(d, 0, sizeof d); 
 54     memset(vis, 0, sizeof vis);
 55     queue<int>q;
 56     q.push(S);
 57     d[S] = 1;
 58     vis[S] = 1;
 59     while (!q.empty())
 60     {
 61         int x = q.front();
 62         q.pop();
 63         for (auto it : G[x])
 64         {
 65             Edge &e = edge[it];
 66             if (!vis[e.to] && e.cap > e.flow)
 67             {
 68                 vis[e.to]
 69                     = 1;
 70                 d[e.to] = d[x] + 1;
 71                 q.push(e.to);
 72             }
 73         }
 74     }
 75     return vis[T];
 76 }
 77 
 78 inline int DFS(int x, int a)
 79 {
 80     if (x == T || a == 0) return a;
 81     int flow = 0;
 82     int f = 0;
 83     for (int &i = cur[x]; i < G[x].size(); ++i)
 84     {
 85         Edge &e = edge[G[x][i]];
 86         if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0)
 87         {
 88             e.flow += f;
 89             edge[G[x][i] ^ 1].flow-f;
 90             flow += f;
 91             a -= f;
 92             if (a == 0) break;
 93         }
 94     }
 95     return flow;
 96 }
 97 
 98 inline int dicnic()
 99 {
100     int ans = 0;
101     while (BFS())
102     {
103         memset(cur, 0, sizeof cur);
104         ans += DFS(S, INF);
105     }
106     return ans;
107 }
108 
109 inline void work()
110 {
111     for (int i = 2; i <= 1000000; ++i)
112     {
113         if (pre[i].size() == 0)
114         {
115             for (int j = i; j <= 1000000; j += i)
116             {
117                 pre[j].push_back(i);
118             }
119         }
120     }
121 }
122 
123 int main()
124 {
125     work();
126     int t;
127     scanf("%d", &t);
128     while (t--)
129     {
130         init();
131         scanf("%d", &n);
132         S = 0, T = n + 1;
133         for (int i = 1; i <= n; ++i)
134         {
135             scanf("%d", &arr[i]);
136         }
137         for (int i = 1; i <= n; ++i)
138         {
139             char c;
140             scanf(" %c", &c);
141             if (c == 'F')
142             {
143                 for (auto it : pre[arr[i]])
144                 {
145                     vec[it].push_back(i);
146                 }
147                 sex[i] = 0;
148             }
149             else
150             {
151                 sex[i] = 1;
152             }
153         }
154         for (int i = 1; i <= n; ++i)
155         {
156             if (sex[i] == 1)
157             {
158                 for (auto j : pre[arr[i]])
159                 {
160                     for (auto k : vec[j])
161                     {
162                         if (mp[make_pair(i, k)] == false)
163                         {
164                             addedge(i, k, 1);
165                             mp[make_pair(i, k)] = mp[make_pair(k, i)] = true;
166                         }
167                     }
168                 }
169             }
170         }
171         for (int i = 1; i <= n; ++i)
172         {
173             if (sex[i] == 1) addedge(0, i, 1);
174             else if (sex[i] == 0) addedge(i, n + 1, 1);
175         }
176         int ans = n - dicnic();
177         printf("%d\n", ans);
178         for (int i = 0; i <= n + 1; ++i)
179         {
180             for (auto x : pre[arr[i]])
181             {
182                 vec[x].clear();
183             }
184         }
185     }
186     return 0;
187 }
View Code

 

 

C:Intersections

题意:给出两个数组,数组里面是相同的数,然后相同的数之间连边,求有多少交点,交点重叠算多个点

思路:从第二个数组开始下手,考虑到当前位置,连边,如果之前的边连的点在当前点连的目标点的后面,就会产生一个点,也就是说统计一下之前有多少个点的目标点在目前这个点的目标点后面,树状数组处理一下

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 100010
 6 #define ll long long
 7 
 8 int t, n;
 9 
10 int a[N], b[N];
11 int id[N];
12 
13 int arr[N];
14 
15 inline int lowbit(int x)
16 {
17     return x & (-x);
18 }
19 
20 inline void update(int x, int val)
21 {
22     for (int i = x; i <= n; i += lowbit(i))
23         arr[i] += val;    
24 }
25 
26 inline int sum(int x)
27 {
28     int ans = 0;
29     for (int i = x; i; i -= lowbit(i))
30         ans += arr[i];
31     return ans;
32 }
33 
34 int main()
35 {
36     scanf("%d", &t);
37     while (t--)
38     {
39         scanf("%d", &n);
40         for (int i = 1; i <= n; ++i) 
41             scanf("%d", a + i), id[a[i]] = i;
42         for (int i = 1; i <= n; ++i)
43             scanf("%d", b + i);
44         memset(arr, 0, sizeof arr);
45         ll ans = 0;
46         for (int i = 1; i <= n; ++i)
47         {
48             int index = id[b[i]];
49             ans += sum(n) - sum(index);
50             update(index, 1);    
51         }
52         printf("%lld\n", ans);
53     }
54     return 0;
55 }
View Code

 

D:Balloons

水。

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

 

E:Maximum Sum

题意:在矩阵中选取部分数,使得权值最大,其中选中的数八个方向的数均不可在选取。、

思路:注意到n很小,可以考虑二进制位表示这个数取不取以及搜索的方法来写。其中遍历每个数的时候,决定这个数能否选取主要取决于这个数的左上角,上方,右上角,左方的数字是否选取。通过一个长度为(1 << 17)的数字表示当前这个数字的左上方到左方的状态。其中第低位表示当前数字的左上方,最高位表示当前数字的左方。在搜索中每个数都有两种状态,取和不取。每次都将当前状态右移一味,去掉没有影响的数字,在添上自己的状态,从而进行下一层的搜索。注意考虑当前数字在这一行第一位和最后一位的情况。最后再添加一点剪枝。

#include<bits/stdc++.h>

using namespace std;

int n;
int ans;

int arr[20][20];

int type[17][17][1 << 17];

inline int DFS(int x, int y, int state)
{
    if (x == n - 1 && y == n) return 0;
    if (y == n) return DFS(x + 1, 0, state);
    if (type[x][y][state] != -1) return type[x][y][state];
    //not
    int res = DFS(x, y + 1, (state >> 1));
    //do
    if (y == 0)
    {
        if (!(state & (1 << 1)) && !(state & (1 << 2))) res = max(res, DFS(x, y + 1, ((state >> 1) | (1 << n))) + arr[x][y]);
    }
    else if (y == n - 1)
    {
        if (!(state & 1) && !(state & (1 << 1)) && !(state & (1 << n))) res = max(res, DFS(x, y + 1, ((state >> 1) | (1 << n))) + arr[x][y]);
    }
    else
    {
        if (!(state & 1) && !(state & (1 << 1)) && !(state & (1 << 2)) && !(state & (1 << n))) res = max(res, DFS(x, y + 1, ((state >> 1) | (1 << n))) + arr[x][y]);
    }
    type[x][y][state] = res;
    return res;
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        memset(type, -1, sizeof type);
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                scanf("%d", &arr[i][j]);
        printf("%d\n", DFS(0, 0, 0));
    }
    return 0;
}
View Code

 

 

F:Working Time

水。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int t, n, m;
 6 
 7 int main()
 8 {
 9     scanf("%d", &t);
10     while (t--)
11     {
12         scanf("%d%d", &n, &m);
13         int tot = 0;
14         int a, b, c, d;
15         for (int i = 1; i <= n; ++i)
16         {
17             scanf("%2d:%2d", &a, &b);
18             scanf("%2d:%2d", &c, &d);
19             int aa = a * 60 + b;
20             int bb = c * 60 + d;
21             tot += abs(aa - bb);
22         }
23         puts(tot >= m * 60 ? "YES" : "NO");
24     }
25     return 0;
26 }
View Code

 

G:Hard Equation

留坑。

(拓展BSGS)

 

H:Cube

水。

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

 

I:Circles

题意:给出圆心,半径,求图中阴影部分面积

思路:四个小圆面积 + 大圆面积 - 矩形面积

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define ll long long
 6 
 7 int t;
 8 ll a, b, d;
 9 
10 int main()
11 {
12     scanf("%d", &t);
13     while (t--)
14     {
15         scanf("%lld%lld%lld", &a, &b, &d);
16         printf("%.10f\n", (d * d) * 1.0 / 2);
17     }
18     return 0;
19 }
View Code

 

J: Smallest Difference

水。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 10010
 5 
 6 int arr[N];
 7 
 8 int main()
 9 {
10     int t;
11     scanf("%d",&t);
12     while(t--)
13     {
14         memset(arr, 0 ,sizeof arr);
15         int n;
16         scanf("%d",&n);
17         for(int i =1;i<=n;++i)
18         {
19             int x;
20             scanf("%d",&x);
21             arr[x]++;
22         }
23         int ans = 0;
24         for(int i = 1;i <= 10000; ++i)
25         {
26             ans = max(arr[i] + arr[i + 1], ans);
27         }
28         printf("%d\n",ans);
29     }
30     return 0;
31 }
View Code

 

 

K:Citations

按题意模拟即可

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 int t, n;
  6 
  7 string s;
  8 
  9 string author, title, journal, volume, number, pages, year;
 10 
 11 inline void Init()
 12 {
 13     author.clear();
 14     title.clear();
 15     journal.clear();
 16     volume.clear();
 17     number.clear();
 18     pages.clear();
 19     year.clear();
 20 }
 21 
 22 inline void work(string &ans)
 23 {
 24     bool flag = false;
 25     for (int i = 0, len = s.size(); i < len; ++i)
 26     {
 27         if (s[i] == '{') 
 28         {
 29             flag = true;
 30             continue;
 31         }
 32         if (s[i] == '}') return;
 33         if (flag == false) continue;
 34         ans += s[i];
 35     }
 36     return;
 37 }
 38 
 39 inline bool Find(string t)
 40 {
 41     if (t.size() > s.size()) return false;
 42     for (int i = 0, len = t.size(); i < len; ++i)
 43     {
 44         if (s[i] != t[i]) return false;
 45     }
 46     return true;
 47 }
 48 
 49 inline void work_author()
 50 {
 51     bool flag = false;
 52     bool fi = false;
 53     int cnt = 0;
 54     for (int i = 0, len = s.size(); i < len; ++i)
 55     {
 56         if (s[i] == '{') 
 57         {
 58             flag = true;
 59             continue;
 60         }
 61         if (s[i] == '}') return;
 62         if (isalpha(s[i]) && flag)
 63         {
 64             if (fi == false)
 65             {
 66                 if(cnt) author += ", ";
 67                 author += s[i];i++;
 68                 author += s[i];
 69                 author += ". ";
 70                 while (s[i] != ' ') i++;
 71                 fi = true;
 72             }
 73             else
 74             {
 75                 author += s[i];
 76                 while (s[i] != ',') i++;
 77                 cnt++;
 78                 fi = false;
 79             }
 80         }
 81     }
 82 }
 83 
 84 int main()
 85 {
 86     cin.tie(0);
 87     cout.tie(0);
 88     ios::sync_with_stdio(false);
 89     cin >> t;
 90     while (t--)
 91     {
 92         cin >> n;
 93         while (n--)
 94         {
 95              Init();
 96              getline(cin, s);
 97             while (getline(cin, s))
 98             {
 99                 if (s == "}") break;
100                 if (Find("author")) work_author();        
101                 else if (Find("title")) work(title);
102                 else if (Find("journal")) work(journal);
103                 else if (Find("volume")) work(volume);
104                 else if (Find("number")) work(number);
105                 else if (Find("year")) work(year);
106                 else if (Find("pages")) work(pages);
107                 else continue;
108             }        
109             cout << author << ". " << title << ". " << journal << ". " << year << ";" << volume << "(" << number << "):" << pages << ".\n";
110         }
111     }
112 }
View Code

 

 


 

 赛后总结:

  • 考虑数据中是否有特殊点会影响答案
  • 模拟题请考虑更多细节
  • 很多东西可以多考虑一点,比如给出的两个数,按题意是需要有大小关系,但是数据不一定保证其大小关系
posted @ 2018-08-11 19:49  Dup4  阅读(1095)  评论(0编辑  收藏  举报