2020大一个人赛(9)题解

 

 

 

A-Rooms and Passages Gym 102215A

题意:给n个数,从起点出发,一直往右走,遇到一个前面出现过其相反数的正数就停下,问对于每个起点都能走多少步。

思路:倒着去递推

  • 如果该点是正数,肯定能顺着走,ans[i]=ans[i+1]+1;
  • 如果该点是负数,判断该相反数是否存在,若不存在,还是ans[i]=ans[i+1]+1,否则走到前面出现过其相反数的正数,r = min(r, b[-a[i]] - 1);      ans[i] = r - i + 1;

具体看代码怎么模拟吧

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 #define ll long long
 7 const int N = 1000005;
 8 const int mod = 1e9 + 7;
 9 ll a[N],b[N],c[N],ans[N];
10 int main()
11 {
12     ll i, j, k;
13     ll n, m, t,x,sum=0;
14     cin >> n;
15     for (i = 1; i <= n; i++)
16         cin >> a[i];
17     ll r = n + 1;
18     for (i = n; i >= 1; i--)
19     {
20         if (a[i] > 0)
21         {
22             ans[i] = ans[i + 1] + 1;
23            b[a[i]] = i;//记录a[i]出现的最靠前的位置
24         }
25         else
26         {
27             if (!b[-a[i]])
28             {
29                 ans[i] = ans[i + 1] + 1;//在i后边没有这种颜色,可通过就是下一个情况加1
30             }
31             else
32             {
33                 r = min(r, b[-a[i]] - 1);//寻找能到达的最靠前的位置
34                 ans[i] = r - i + 1;
35             }
36         }
37     }
38     for (i = 1; i <= n; i++)
39         cout << ans[i] << " ";
40    
41 
42 }

B - Rearrange Columns Gym - 102215B

题意:有两行字符串,有‘#’和‘.’,问能否重排(列一起移),使他们连在一起。

思路:模拟即可,判断一下两行都是#的一定能有办法连在一起,或者上面有#下面(相反也是),然后连完之后你怎么排也无所谓(样例不一定就是唯一解)

详情看代码吧!

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 1e5+5;
 9 const int mod = 1e9 + 7;
10 int main()
11 {
12     ll i, j, k;
13     ll  m, t;
14     string s1, s2;
15     cin >> s1 >> s2;
16     ll n = s1.size();
17     ll a = 0, b = 0, c = 0;
18     for (i = 0; i < n; i++)
19     {
20         if (s1[i] == '#' && s2[i] == '#')a++;
21         else if (s1[i] == '#' && s2[i] == '.')b++;
22         else if (s1[i] == '.' && s2[i] == '#')c++;
23     }
24     if (a || (b && !c) || (c && !b))
25     {
26         cout << "YES" << endl;
27         {
28             for (i = 0; i < n - a - b - c; i++)
29                 cout << '.';
30             for (i = 0; i < a + b; i++)
31                 cout << '#';
32             for (i = 0; i < c; i++)
33                 cout << '.';
34             cout << endl;
35             for (i = 0; i < n - a - b - c; i++)
36                 cout << '.';
37             for (i = 0; i < b; i++)
38                 cout << '.';
39             for (i = 0; i < a+c; i++)
40                 cout << '#';
41             cout << endl;
42         }
43     }
44     else
45         cout << "NO" << endl;
46    
47 
48 }

C - Jumps on a Circle Gym - 102215C

 题意:一个环从0到p-1,从0开始每次跳1,2,3,···,n-1,n步,问跳n步之后会有多少个位置访问过。

思路:弄一个vis数组,表示访问过的点,注意p为1e7,数组开大点(RE很多次),或者用map记录,去到没标过的点就+1

   然后若n>2p,2p次后又一定回到点原点,然后2p+1,2p+2步的效果相当于1,2步(%p就知道了)

 

 这时候观众朋友们告诉我,为什么不是p次呢,因为

 

 你带4进去就知道原因了。所以最少走min(n,2p)次就能知道访问过的点了。

详情问代码吧!

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 #define ll long long
 7 const int N = 1e7+5;
 8 const int mod = 1e9 + 7;
 9 ll vis[N];
10 int main()
11 {
12     ll i, j, k;
13     ll p,n, m, t,x,sum=0;
14     cin >> p >> n;
15     vis[0] = 1;
16     ll now = 0;
17     for (i = 1; i <= min(n, 2 * p); i++)
18     {
19         now = (now + i) % p;
20         vis[now] = 1;
21     }
22     for (i = 0; i < p; i++)
23         sum += vis[i];
24     cout << sum << endl;
25    
26 
27 }

 D - Country Division Gym - 102215D

题意:给你n点,n-1条边(相当于一棵树),每次询问给你一些点染红色,一些点蓝色,问能否通过放些障碍物在边上,使得所有红色的点互相连通,所有蓝色的点连通,而不互相碰见。

思路:LCA(最近公共祖先),就是找公共的父节点,这题是一道LCA经典题,各位可以认真细品题目,get到新知识点你就会成长,至于问怎么实现LCA原理的,我没了解过OvO

 

 解释下LCA,比如4和5的公共父节点是2;4和6的LCA是1;5和7的LCA是1;6和7的LCA是3.

正解思路:

  • 先求红色点的lca,再求蓝色点的lca,如果两个lca不在同一棵子树,那么可以分隔开来。
  • 如果两个lca有祖先关系,比如红色lca和蓝色lca的lca就是红色lca,那么如果红色点都在红色lca指向蓝色lca的另一条边上,那就可以,否则,说明有红色点在蓝色点的子树下

下面看代码吧

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<cstdio>
  5 #include<cstdlib>
  6 #include<cstring>
  7 #include<math.h>
  8 #include<map>
  9 #include<vector>
 10 #include<set>
 11 #include<queue>
 12 #define fori for(i=0;i<n;i++)
 13 #define fori1 for(i=1;i<=n;i++)
 14 #define inf 9999999
 15 #define Check(x,y) (x<n&&x>=0&&y>=0&&y<m)
 16 #define IOS ios::sync_with_stdio(false);cin.tie(0)
 17 #define ll long long
 18 #define inf 0x3f3f3f3f
 19 #define eps 1e-6
 20 #define pi acos(-1)
 21 #define mea (memset(a,0,sizeof(a)))
 22 #define myit set<ll>::iterator
 23 #define mysets multiset<ll>
 24 #define myits multiset<ll>::iterator
 25 #define v30 (1<<30)-1
 26 #define all(x) (x).begin(),(x).end()
 27 #define maxs *s.rbegin()
 28 #define lowbit(x) (x&(-x))
 29 #define mid ((a[k].r+a[k].l)>>1)
 30 #define lson k<<1,l,mid
 31 #define rson k<<1|1,mid+1,r
 32 #define kl k<<1
 33 #define kr k<<1|1
 34 #define ispow(n) (n & (n - 1))
 35 using namespace std;
 36 const ll N=1000005;
 37 const ll mod = 1e9 + 7;
 38 const ll de = 2e9 + 1;
 39 inline ll read() {
 40     ll s = 0, w = 1;
 41     char ch = getchar();
 42     while (ch < '0' || ch>'9') { if (ch == '-')w = -1; ch = getchar(); }
 43     while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
 44     return s * w;
 45 }
 46 void put1() { puts("YES"); }
 47 void put2() { puts("NO"); }
 48 void put3() { puts("-1"); }
 49 ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
 50 using namespace std;
 51 
 52 const int manx = 2e5 + 5;
 53 
 54 ll head[manx], d[manx], f[manx][21], lg[manx];
 55 ll k = 0;
 56 struct node {
 57     ll v, next;
 58 }e[manx * 2];
 59 void add(ll u, ll v) {
 60     e[++k].v = v;
 61     e[k].next = head[u];
 62     head[u] = k;
 63 }
 64 void dfs(ll u, ll fa) {
 65     d[u] = d[fa] + 1;
 66     f[u][0] = fa;
 67     for (int i = 1; i <= lg[d[u]]; i++)
 68         f[u][i] = f[f[u][i - 1]][i - 1];
 69     for (int i = head[u]; i; i = e[i].next)
 70         if (e[i].v != fa)
 71             dfs(e[i].v, u);
 72 }
 73 ll lca(ll a, ll b) {
 74     if (d[a] < d[b]) swap(a, b);
 75     while (d[a] > d[b]) a = f[a][lg[d[a] - d[b]] - 1];
 76     if (a == b) return a;
 77     for (int i = lg[d[a]] - 1; i >= 0; i--)
 78         if (f[a][i] != f[b][i])
 79             a = f[a][i], b = f[b][i];
 80     return f[a][0];
 81 }
 82 int red[200050],blue[200050];
 83 int main()
 84 {
 85     ll i, j, k;
 86     ll n, m, t;
 87     ll r, b,q;
 88     cin >> n;
 89         for (int i = 1; i < n; i++) {
 90             ll u = read(), v = read();
 91             add(u, v);
 92             add(v, u);
 93         }
 94         for (int i = 1; i <= n; i++)
 95             lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
 96         dfs(1, 0);
 97         cin >> q;
 98         while (q--)
 99         {
100             cin >> r >> b;
101             cin >> red[1];
102             int rlca = red[1];
103             for (i = 2; i <= r; i++)
104             {
105                 cin >> red[i];
106                 rlca = lca(rlca, red[i]);
107             }
108             cin >> blue[1];
109             int blca = blue[1];
110             for (i = 2; i <= b; i++)
111             {
112                 cin >> blue[i];
113                 blca = lca(blca, blue[i]);
114             }
115             int zonglca = lca(rlca, blca);
116             if (rlca != zonglca && blca != zonglca)
117             {
118                 cout << "YES" << endl;
119             }
120             else if (rlca == zonglca)
121             {
122                 int flag = 0;
123                 for ( i = 1; i <= r; i++)
124                 {
125                     if (lca(red[i], blca) == blca)
126                     {
127                         cout << "NO" << endl;
128                         flag = 1;
129                         break;
130                     }
131                 }
132                 if (!flag)
133                     cout << "YES" << endl;
134             }
135             else if (blca == zonglca)
136             {
137                 int flag = 0;
138                 for (i = 1; i <= b; i++)
139                 {
140                     if (lca(blue[i], rlca) == rlca)
141                     {
142                         cout << "NO" << endl;
143                         flag = 1;
144                         break;
145                     }
146                 }
147                 if (!flag)
148                     cout << "YES" << endl;
149             }
150         }
151 
152 }

 

E - Third-Party Software - 2  Gym - 102215E 

 

题意:求用最少的线段覆盖整个区间,并且输出你用的线段

思路:贪心,排序左端点从小到大,若左端点相同则取右端点从大到小排序,然后遍历即可。

献上代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 2e5+5;
 9 const int mod = 1e9 + 7;
10 struct node {
11     ll l, r;
12     ll id;
13 }s[N];
14 bool cmp(const node& a, const node& b)
15 {
16     if (a.l == b.l)return a.r > b.r;
17     return a.l < b.l;
18 }
19 vector<ll>G;
20 int main()
21 {
22     ll i, j, k;
23     ll  n,m, t;
24     cin >> n >> m;
25     for (i = 0; i < n; i++)
26     {
27         cin >> s[i].l >> s[i].r;
28         s[i].id = i;
29     }
30     sort(s, s + n, cmp);
31     ll now = 1, ans = 0;
32     i = 0;
33     while (i <= n && now <= m)
34     {
35         ll maxn = 0;
36         k = 0;
37         while (i <= n && s[i].l <= now)
38         {
39             if (s[i].r > maxn)
40             {
41                 maxn = s[i].r;
42                 k = i;
43             }
44             i++;
45         }
46         if (maxn <= now - 1)
47         {
48             ans = -1;
49             break;
50         }
51         G.push_back(s[k].id+1);
52         now = maxn + 1;
53         ans++;
54     }
55     if (now <= m)//不能包括所有点
56         ans = -1;
57     if (ans == -1)
58         cout << "NO" << endl;
59     else
60     {
61         cout << "YES" << endl;
62         cout << ans << endl;
63         for (i = 0; i < ans; i++)
64             cout << G[i] << " ";
65     }
66     
67    
68 
69 }

F - The Power of the Dark Side - 2    Gym - 102215J 

题意:给你n个野蛮人(绝地武士)能力值a,b,c,两个武士决斗时谁有两个值大于对方谁就是胜者(a和a比,b和b比,c和c比,所有武士的三个值都不相同),现在可以交换任意武士的三个能力值位置,问有些可以击败其余所有武士。

思路:贪心排序能力,先将自己能力进行排序,然后将打败下限(即最小能力+1和次小能力+1)进行排序,再二分upper_bound属个数,再判断有没有自己揍自己就行。

献上代码(我提交的MV c++2017才不T)

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 5e5+25;
 9 const int mod = 1e9 + 7;
10 ll s[N][3];
11 ll sum[N];
12 int i, j, k;
13 ll  n,m, t;
14 vector<ll>v;
15 vector<int>ans;
16 int main()
17 {
18     
19     scanf("%d", &n);
20     for (i = 1; i <= n; i++)
21     {
22         cin >> s[i][0] >> s[i][1] >> s[i][2];
23         sum[i] = s[i][0] + s[i][1] + s[i][2];
24         sort(s[i], s[i] + 3);
25         v.push_back(s[i][0] + s[i][1]+2);//注意,+2这里是次大被打败需要加一,最小被打败也要+1
26     }
27     sort(v.begin(), v.end());
28     for (i = 1; i <= n; i++)
29     {
30         int k = upper_bound(v.begin(), v.end(), sum[i]) - v.begin();
31         ll t = sum[i] - (s[i][0] + s[i][1] + 2);
32         if (t >= 0)
33             k--;//减去我自己打自己
34         ans.push_back(k);
35     }
36     for (i = 0; i < n; i++)
37         printf("%d ", ans[i]);
38 }

G - Bashar and the bad land (Hard) Gym - 102397E

题意:给你一个n个数和x,问最短的区间和大于等于x

思路:前缀和+尺取法,在1点先弄一个长度(假设为R)刚好区间和大于等于x,然后从R点向右移动,然后1点一直尺取收缩使得刚好大于等于x,详情看代码吧。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 #define ll long long
 7 const int N = 1000005;
 8 const int mod = 1e9 + 7;
 9 ll a[N],b[N],c[N];
10 int main()
11 {
12     ll i, j, k;
13     ll n, m, t,x,sum=0;
14     cin >> n >> x;
15     for (i = 1; i <= n; i++)
16     {
17         cin >> a[i];
18         sum += a[i];
19     }
20     if (sum < x)
21         cout << -1 << endl;
22     else
23     {
24         a[0] = 0;
25         for (i = 1; i <= n; i++)
26         {
27             b[i] = b[i - 1] + a[i];
28         }
29        /* for (i = 1; i <= n; i++)
30         {
31             cout << b[i] << " ";
32         }*/
33         for (i = 1; i <= n; i++)
34             if (b[i] > x)
35                 break;
36        // cout << endl << i << endl;
37         ll l = 1, r = i,ans=i,cnt=b[r];
38         for(j=i;j<=n;j++)
39         {
40             cnt = b[j]-b[l-1];
41             while (b[j] - b[l] >= x)
42                 l++;
43             ans = min(ans, j - l + 1);
44            // cout << cnt << endl;
45         }
46         cout << ans << endl;
47         
48     }
49 
50 }

H - Deck Sorting Gym - 102215K 

题意:给你只含RGB的字符串,从中抽出一个子序列,和剩下的子序列拼在一起,使得拼接后的字符串相同字符在一起。

思路:枚举6种全排列方式,比如RGB,先取全部R,G留下,然后最后一个R连接后面B,第一个G连接前面的B,若拼起来的长度不够原来的长度,则枚举下一种,直到没有符合输出NO。

代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 5e5+25;
 9 const int mod = 1e9 + 7;
10 char ju[6][3] = {
11     {'R','G','B'},{'R','B','G'},
12     {'G','R','B'},{'G','B','R'},
13     {'B','G','R'},{'B','R','G'}
14 };
15 vector<char>s1;
16 vector<char>s2;
17 int main()
18 {
19     ll i, j, k;
20     string s;
21     ll n;
22     cin >> s;
23     n = s.size();
24     int flag = 0;
25     for (i = 0; i < 6; i++)
26     {
27         ll sum1 = 0, sum2 = 0;
28         ll pos1 = 0, pos2 = 0;
29         for (j = 0; j < n; j++)
30         {
31             if (s[j] == ju[i][0])
32             {
33                 sum1++;
34                 pos1 = j;//标记最后一个点
35             }
36             if (s[j] == ju[i][2])
37             {
38                 sum2++;     
39             }
40         }
41         for (j = 0; j < n; j++)
42         {
43             if (s[j] == ju[i][2])
44             {
45                 pos2 = j;//标记第一个点
46                 break;
47             }
48         }
49         for (j = 0; j < pos2; j++)
50             if (s[j] == ju[i][1])
51                 sum2++;
52         for (j = n - 1; j > pos1; j--)
53             if (s[j] == ju[i][1])
54                 sum1++;
55         if (sum1 + sum2 == n)
56         {
57             flag = 1;
58             break;
59         }
60     }
61     if (flag)
62         cout << "YES" << endl;
63     else
64         cout << "NO" << endl;
65 }

 

posted @ 2020-04-24 17:16  ch_hui  阅读(275)  评论(0编辑  收藏  举报