Codeforces Round #614 (Div. 2) A-E简要题解

Posted aaronchang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #614 (Div. 2) A-E简要题解相关的知识,希望对你有一定的参考价值。

链接:https://codeforces.com/contest/1293

 

A. ConneR and the A.R.C. Markland-N

题意:略

思路:上下枚举1000次扫一遍,比较一下上下最近的房间

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<map>
 6 #include<utility>
 7 #include<string>
 8 #include<vector>
 9 #include<cstring>
10 #include<iostream>
11 #include<vector>
12 #include<algorithm>
13 #include<cmath>
14 #include<cstring>
15 #include<queue>
16 #include<cstdio>
17 #include<unordered_map>
18 using namespace std;
19 const int maxn=1e5;
20 typedef long long ll;
21 
22 int main()
23 {
24     int t;
25     cin >> t;
26     while(t--)
27     {
28         map<int,int> v;
29         int n,s,k;
30         scanf("%d%d%d",&n,&s,&k);
31         int x;
32         for(int i=1; i<=k; i++)
33         {
34 
35             scanf("%d",&x);
36             v[x]++;
37         }
38         int l,r;
39         l=r=s;
40         if(!v[s])
41             cout << 0 << endl;
42         else
43         {
44             while(v[l]&&v[r])
45             {
46                 if(l-1>=1)
47                     l--;
48                 if(r+1<=n)
49                     r++;
50 
51             }
52             if(!v[r]&&!v[l])
53             {
54                 cout << min(s-l,r-s) << endl;
55             }
56             else if(!v[r]&&v[l])
57             {
58                 cout << r-s<< endl;
59             }
60             else if(v[r]&&!v[l])
61                 cout << s-l << endl;
62         }
63     }
64     return 0;
65 }

 

B. JOE is on TV!

 

题意:略

思路:比较简单,推结论 max (n) = i/n+(i-1)/n + ...n/n

AC代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<queue>
 7 #include<cstdio>
 8 #include<unordered_map>
 9 using namespace std;
10 typedef long long ll;
11 int main(){
12     int t;
13     float ans = 0;
14     scanf("%d",&t);
15     float i = 1;
16     while(i<=t){
17         ans+=(1/i);
18         i+=1;
19     }
20     printf("%.12lf",ans);
21     return 0;
22 }

 

 

C. NEKO‘s Maze Game

题意:有一个2×n的网格迷宫,网格可以翻动,由正常区域和堵塞区域切换,问从(1,1)能否到(2,n)

思路:一个网格如果翻动,如果这个网格是在第二列,那么这个网格可以和其左上角、正上方、右上角构成堵塞,这样算是三个“堵塞贡献”,如果位于第一列翻动由正常区域变成堵塞,那么这个网格可以和左下角、正下方、右下方的网格构成堵塞区域,这样也是三个贡献,每次放置网格就计算上这些贡献,换回正常的时候就减去,如果总的贡献是0,那么就可以到达(2,n)

AC代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<queue>
 7 #include<cstdio>
 8 #include<unordered_map>
 9 using namespace std;
10 typedef long long ll;
11 const int maxn = 1e5+15;
12 int grid[2][maxn];
13 int can[maxn];
14 int main(){
15     int n,q;
16     int cnt = 0;
17     scanf("%d%d",&n,&q);
18     while(q--){
19         int x,y;
20         scanf("%d%d",&x,&y);
21         x = x - 1;
22         if((grid[0][y]+grid[1][y]) == 2){
23             cnt--;
24         }
25         if(grid[x][y]+grid[(x+1)%2][y-1] == 2){
26             cnt--;
27         }
28         if(grid[x][y]+grid[(x+1)%2][y+1] == 2){
29             cnt--;
30         }
31         grid[x][y] = (grid[x][y]+1)%2;
32         if((grid[0][y]+grid[1][y]) == 2 ){
33             cnt++; 
34         }
35         if(grid[x][y]+grid[(x+1)%2][y-1] == 2 ){
36             cnt++; 
37         }
38         if(grid[x][y]+grid[(x+1)%2][y+1] == 2 ){
39             cnt++; 
40         }
41         if(cnt == 0){
42             printf("YES
");
43         }
44         else printf("NO
");
45     }
46     return 0;
47 }

 

D. Aroma‘s Search

题意:二维平面上有若干个点,第i个点的坐标(xi,yi)满足xi=xi-1*ax+bx,yi=y-1*ay+by,已知 ax,bx,ay,by,x0,y0 以及初始位置(xs,ys),每秒钟可以往上下左右走1个单位,则在t秒内最多可以走到多少个点

思路:所有点之间的曼哈顿距离是乘指数级别增长的,不能到了一个点之后再回到初始点,也不能从距离最近的点开始出发去枚举。考虑到数据范围,其实点的极限数量大概在60多,所以可以构造一个暴力的算法去枚举。最佳的方案是先从起点到其中一个点,再从这个点向下面的点移动,因为向上比向下距离远,如果下方所有的点都可以到达,再往上走,这样是最佳的方案。所有需要枚举起点到每一个点,再从该点先向下方移动再向上移动

AC代码:

 

 1     #include<bits/stdc++.h>
 2     using namespace std;
 3     typedef long long ll;
 4     ll x0,y0,ax,ay,bx,by,xs,ys,t;
 5     vector<pair<ll,ll> > v;
 6     ll solve(int x){
 7         ll remain = t;
 8         remain -= abs(v[x].first-xs)+abs(v[x].second-ys);
 9         if(remain<0) return 0;
10         ll res = 1;
11         int last = x;
12         for(int i = x-1;i>=0;i--){
13             ll can = abs(v[i].first-v[last].first)+abs(v[i].second-v[last].second);//先向下方的点移动
14             if(remain-can<0) break;
15             res++;
16             remain-=can; 
17             last = i;
18         }
19         for(int i = x+1;i<v.size();i++){
20             ll can = abs(v[i].first-v[last].first)+abs(v[i].second-v[last].second);//如果还有时间剩余向上方点移动
21             if(remain-can<0) break;
22             res++;
23             remain-=can; 
24             last = i;    
25         }
26         return res;
27     }
28     int main(){
29         cin>>x0>>y0>>ax>>ay>>bx>>by;
30         cin>>xs>>ys>>t;
31         ll curx = x0,cury = y0;
32         while(1){
33             ll disX = abs(curx-xs);
34             ll disY = abs(cury-ys);
35             if(curx>xs && cury>ys && disX+disY > t) break;//如果移动到该点就超过了t秒,break
36             v.push_back({curx,cury});
37             curx = ax*curx+bx;
38             cury = ay*cury+by;
39         }
40         ll ans = 0;
41         for(int i = 0;i<v.size();i++){
42             ans = max(ans,solve(i));//枚举到每个点
43         }
44         cout<<ans;
45         return 0;
46     }

 

 

 

 

E. Xenon‘s Attack on the Gangs

题意:给出一颗树,树上随机分配边权值,不存在权值相同的两条边,定义mex(u,v)表示点u到点v经过边的边权集合S中没有出现的最小非负整数,求S = ∑mex(u,v) (1<=u<=v<=n)的最大值。

思路:这道题没有太明白,看官方题解首先要推出一个组合公式,问题转化为求一条边的贡献,对u到v的路径进行dp,枚举u到v的每一条路径的贡献。

放个官方题解吧

 

技术图片

 

 

技术图片

 

 

AC代码:

 1 #include<bits/stdc++.h> 
 2 using namespace std;
 3 const int maxn = 3005;
 4 typedef long long ll;
 5 int fa[maxn][maxn],sub[maxn][maxn];
 6 ll dp[maxn][maxn];
 7 vector<int> G[maxn]; 
 8 int n,root;
 9 int dfs(int cur,int father){
10     sub[root][cur] = 1;
11     for(int i = 0;i<G[cur].size();i++){
12         if(G[cur][i]!=father){
13             fa[root][G[cur][i]] = cur;
14             sub[root][cur]+=dfs(G[cur][i],cur);
15         }
16     }
17     return sub[root][cur];
18 }
19 ll getDp(int u,int v){
20     if(u == v) return 0;
21     if(dp[u][v] ) return dp[u][v];
22     return dp[u][v] = sub[u][v]*sub[v][u] + max(getDp(fa[v][u],v),getDp(fa[u][v],u));
23 }
24 int main(){
25     scanf("%d",&n);
26     for(int i = 1;i<n;i++) {
27         int u,v;
28         cin>>u>>v;
29         G[u].push_back(v),G[v].push_back(u);  
30     }
31     for(int i = 1;i<=n;i++){
32         root = i;
33         dfs(i,-1);
34     }
35     ll res = 0;
36     for(int i = 1;i<=n;i++){
37         for(int j = 1;j<=n;j++){
38             res = max(res,getDp(i,j));
39         }
40     }
41     printf("%lld",res);
42     return 0;
43 }

 

以上是关于Codeforces Round #614 (Div. 2) A-E简要题解的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #614 (Div. 2)

Codeforces Round #614 (Div. 2)

Codeforces Round #614 选讲

Codeforces Round #614 (Div. 2)

Codeforces Round #614 (Div. 2)

Codeforces Round #614 (Div. 2) A-E简要题解