首页 > 代码库 > Codeforces Round #379 (Div. 2) Analyses By Team:Red & Black

Codeforces Round #379 (Div. 2) Analyses By Team:Red & Black

A.Anton and Danik

Problems: 给你长度为N的,只含‘A’,‘D‘的序列,统计并输出何者出现的较多,相同为"Friendship"

Analysis:

  lucky_ji: 水题,模拟统计A和D的数目比较大小输出结果即可

Tags: Implementation

 

B.Anton and Digits

Problems: 给定k2个2,k3个3,k5个5及k6个6,可以组成若干个32或256,求所有方案中Sigma的最大值

Analysis:

  lucky_ji: 同样是水题 贪心先构造256,再构造32就行 一个式子出结果 Ans=min({k2,k5,k6})*256+min(k2-min({k2,k5,k6}),k3)*32

Tags: Greedy

 

C.Anton and Making Potions

Problems: 给定n个单位,每个单位花费为x,同时给定初始魔法值s,有两种咒语,每种至多使用一个,第一类有m个,消耗d_i,可以让所有单位花费变为a_i,第二类有k个,消耗d_i, 可以让c_i个单位花费变为0,求最小总花费。输入保证c_i, d_i单调递增

Analysis:

  lucky_ji2类药剂代价和效果输入均满足不递减,故可以用二分搜索 首先先把单用一种药剂的最小代价求出,对于每一种1类药剂,其代价为X,总可用代价为V,二分查找组合使用的效果最好的2类药剂,查找条件是所有代价Y满足X+Y<V的药剂中,在输入序列中最靠后的。枚举1类药剂,找出用两瓶药剂能得到的最小价值,取两个最小价值中较小的那个。若一瓶药剂都不能使用,输出没使用药剂的代价。

                   P.s. 注意数据规模,int越界。

Tags: Dynamic Programming, Binary search, Greedy

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<string>
 6 #include<vector>
 7 #include<stack>
 8 #include<bitset>
 9 #include<cstdlib>
10 #include<cmath>
11 #include<set>
12 #include<list>
13 #include<deque>
14 #include<fstream>
15 #include<math.h>
16 #include<map>
17 #include<queue>
18 #include <iomanip>
19 #include<stdio.h>
20 using namespace std;
21 const double PI=acos(-1.0);
22 const double eps=1e-10;
23 #define Max(a,b) (a)>(b)?(a):(b)
24 #define Min(a,b) (a)<(b)?(a):(b)
25 long long n,m,k,x,s,a[200010][2],b[200010][2],now;
26 long long ans,qwe;
27 long fi(long x){
28     long s,t,now;
29     if (b[0][0]>x)
30         return -1;
31     s=1;
32     t=k;
33     now=(s+t)/2;
34     while (!((s==t)||(b[now-1][0]==x)||((s+1)==t))){
35         if (b[now-1][0]>x){
36             t=now;
37             now=(s+t)/2;
38         }
39         else{
40             s=now;
41             now=(s+t)/2;
42         }
43     }
44     while (((now+1)<=k)&&(b[now][0]<=x)){
45         now++;
46     }
47     return now-1;
48 }
49 int main(){
50     scanf("%d%d%d%d%d",&n,&m,&k,&x,&s);
51     ans=n*x;
52     for (int i=0;i<m;i++){
53         scanf("%d",&a[i][1]);
54     }
55     for (int i=0;i<m;i++){
56         scanf("%d",&a[i][0]);
57         if (a[i][0]<=s)
58             ans=Min(ans,n*(a[i][1]));
59     }
60     for (int i=0;i<k;i++){
61         scanf("%d",&b[i][1]);
62     }
63     for (int i=0;i<k;i++){
64         scanf("%d",&b[i][0]);
65         if (b[i][0]<=s)
66             ans=Min(ans,(n-b[i][1])*x);
67     }
68     for (int i=0;i<m;i++){
69         qwe=s-a[i][0];
70         now=fi(qwe);
71         if (now!=-1)
72             ans=Min(ans,(n-b[now][1])*(a[i][1]));
73     }
74     printf("%lld\n",ans);
75     return 0;
76 }
Code by lucky_ji
技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 //#include<iostream>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 #include<string>
 9 #include<vector>
10 using namespace std;
11 #define INF (1ll<<62)
12 #define Clear(x, Num) memset(x, Num, sizeof(x))
13 #define Dig(x) ((x>=‘0‘) && (x<=‘9‘))
14 #define Neg(x) (x==‘-‘)
15 #define G_c() getchar()
16 #define Maxn 200010
17 typedef long long ll;
18 
19 int n, m, k, x, s;
20 int a[Maxn], b[Maxn], c[Maxn], d[Maxn];
21 
22 inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
23 inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
24 //inline void Insert(int u, int v) { To[Cnt]=v; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
25 
26 inline int Find(int x)
27 {
28     int l=0, r=k;
29     while (l<=r)
30     {
31         int mid=(l+r)>>1;
32         if (d[mid]<=x) l=mid+1; else r=mid-1;
33     }
34     return l;
35 }
36 
37 int main()
38 {
39     read(n); read(m); read(k); read(a[0]); read(s);
40     for (int i=1; i<=m; i++) read(a[i]);
41     for (int i=1; i<=m; i++) read(b[i]);
42     for (int i=1; i<=k; i++) read(c[i]); 
43     for (int i=1; i<=k; i++) read(d[i]);
44     ll Res=INF;
45     for (int i=0; i<=m; i++)
46         if (s-b[i]>=0)
47         {
48             int Cur=Find(s-b[i]);
49             Res=min(Res, (ll)a[i]*(n-c[Cur-1]));
50         }
51     printf("%lld\n", (Res==INF)?(-1):(Res));
52 }
Code by Return
技术分享
 1 #define PRON "734c"
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 #define inf 0x3f3f3f3f
 6 using namespace std;
 7 typedef long long ll;
 8 
 9 const int MAXN = 200000 + 5;
10 
11 ll ans;
12 int n, m, k, x, s, a[MAXN], b[MAXN], c[MAXN], d[MAXN];
13 
14 int main(){
15 #ifndef ONLINE_JUDGE
16     freopen(PRON ".in", "r", stdin);
17 #endif
18 
19     cin >> n >> m >> k >> x >> s;
20     for (int i = 0; i < m; i ++)
21         scanf("%d", a + i);
22     for (int i = 0; i < m; i ++)
23         scanf("%d", b + i);
24     for (int i = 0; i < k; i ++)
25         scanf("%d", c + i);
26     for (int i = 0; i < k; i ++)
27         scanf("%d", d + i);
28         
29     ans = ((ll)n - c[upper_bound(d, d + k, s) - d - 1]) * (ll)x;
30     for (int i = 0; i < m; i ++)
31         if (b[i] <= s){
32             int p = upper_bound(d, d + k, s - b[i]) - d - 1;
33             ans = min(ans, (ll)(n - c[p]) * (ll)a[i]);
34         }
35 
36     cout << ans << endl;
37 }
Code by cj

 

D.Anton and Chess

Problems: 在国际象棋规则背景下,给定King的初始位置,和n个棋子的位置,其中棋子有Bishop,Rook和Queen三种,问是否可以移动某一个棋子使得在一步之内使游戏结束(结束条件为国王死亡)

Analysis:

  lucky_ji:简单的模拟题,不难,注意细节就行。存储8个方向(上、下、左、右、左上、左下、右上、右下)上离国王最近的棋子,判断是否被将死即可。

  cj:我原来喜欢用的const int inf = ox3f3f3f3f小了

Tags: Implementation

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 //#include<iostream>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 #include<string>
 9 #include<vector>
10 using namespace std;
11 #define INF 2100000000
12 #define Clear(x, Num) memset(x, Num, sizeof(x))
13 #define Dig(x) ((x>=‘0‘) && (x<=‘9‘))
14 #define Neg(x) (x==‘-‘)
15 #define G_c() getchar()
16 #define Pend ((ch==‘R‘) || (ch==‘Q‘))
17 typedef long long ll;
18 
19 int n, x0, _y0, x, y, l, r, u, d, Opt_l, Opt_r, Opt_u, Opt_d, Jge[10][10], Opt[10][10];
20 char ch;
21 
22 inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
23 inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
24 //inline void Insert(int u, int v) { To[Cnt]=v; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
25 
26 int main()
27 {
28     scanf("%d", &n);
29     read(x0); read(_y0);
30     l=r=u=d=Jge[0][0]=Jge[0][1]=Jge[1][0]=Jge[1][1]=INF;
31     for (int i=1; i<=n; i++)
32     {
33         ch=G_c(); while ((ch^R) && (ch^Q) && (ch^B)) ch=G_c();
34         read(x); read(y); int Lim_y=abs(_y0-y), Lim_x=abs(x0-x);
35         if (x==x0)
36         {
37             if (y<_y0)
38                 if (l>=_y0-y) l=Lim_y, Opt_l=Pend; else;
39             else
40                 if (r>=y-_y0) r=Lim_y, Opt_r=Pend; else;
41         }
42         else
43             if (y==_y0)
44             {
45                 if (x<x0)
46                     if (u>=x0-x) u=Lim_x, Opt_u=Pend; else;
47                 else
48                     if (d>=x-x0) d=Lim_x, Opt_d=Pend; else;
49             }
50             else
51                 if ((Lim_x==Lim_y) && (Jge[x>x0][y>_y0]>Lim_x))
52                 {
53                     Jge[x>x0][y>_y0]=Lim_x;
54                     Opt[x>x0][y>_y0]=((ch==B) || (ch==Q));
55                 }
56     }
57     bool flag=((Opt_l) || (Opt_r) || (Opt_u) || (Opt_d) || (Opt[0][0]) || (Opt[0][1]) || (Opt[1][0]) || (Opt[1][1]));
58     puts(flag?"YES":"NO");
59 }
Code by Return
技术分享
 1 #define PRON "734d"
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 
 9 const int inf = 2000000000 + 10;
10 const int maxn = 500000 + 10;
11 
12 char t;
13 pair<int, int> b[5][5], r[5][5];
14 int n, x, y, _x, _y, sb[5][5], sr[5][5];
15 
16 int sig(int now){
17     if (now < 0)
18         return 0;
19     if (now > 0)
20         return 2;
21     return 1;
22 }
23 
24 bool check(){
25     for (int i = 0; i < 3; i ++)
26         for (int j = 0; j < 3; j ++)
27             b[i][j] = r[i][j] = make_pair(inf, inf);
28 
29     int _t;
30     for (int i = 0; i < n; i ++){
31         cin >> t >> _x >> _y;
32         _x -= x, _y -= y;
33         if (t == B)
34             _t = 1;
35         else if (t == R)
36             _t = 2;
37         else
38             _t = 3;
39 
40         if (abs(_x) == abs(_y) && abs(_x) < abs(b[sig(_x)][sig(_y)].first))
41             b[sig(_x)][sig(_y)] = make_pair(_x, _y), sb[sig(_x)][sig(_y)] = _t;
42 
43         if (_x == 0 && abs(_y) < abs(r[sig(_x)][sig(_y)].second))
44             r[sig(_x)][sig(_y)] = make_pair(_x, _y), sr[sig(_x)][sig(_y)] = _t;
45 
46         if (_y == 0 && abs(_x) < abs(r[sig(_x)][sig(_y)].first))
47             r[sig(_x)][sig(_y)] = make_pair(_x, _y), sr[sig(_x)][sig(_y)] = _t;
48     }
49 
50     for (int i = 0; i < 3; i ++)
51         for (int j = 0; j < 3; j ++)
52             if ((b[i][j].first != inf && sb[i][j] != 2) || (r[i][j].first != inf && sr[i][j] != 1))
53                 return true;
54 
55     return false;
56 }
57 
58 int main(){
59 #ifndef ONLINE_JUDGE
60     freopen(PRON ".in", "r", stdin);
61 #endif
62 
63     cin >> n >> x >> y;
64 
65     puts(check() ? "YES" : "NO");
66 }
Code by cj

 

E.Anton and Tree

Problems: 给定一个有n个点的树,树上点有黑白两色,每次可以执行paint操作,该操作可以使和这个点相连的所有同色点颜色取反,且代价为1,问最小代价

Analysis:

  lucky_ji: 稍有点难度,首先DFS把相同颜色的点缩为一个点,得到一个树,问题变为每次可以对得到的树中的一个节点进行一次操作,操作会使一个节点将周围的点吞掉并合并为一个节点。目标是使树只剩一个点。那么问题就变成了最少经过几次操作后能使树的直径为1,答案显然为树的直径div 2,每次都是对直径的中点进行操作,所以在缩点后只要进行两次BFS求出直径,再div2即为答案。

  Return: 考虑到lucky_ji解答中的的缩点再搜索,其实对比两颗树可以发现,新树的直径可以通过在dfs维护dep得到,而显然,只有该节点颜色和其父节点不同时,才考虑dep+1,从而有效减少了代码量

Tags: Dfs and Similar, Trees

技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<string>
  6 #include<vector>
  7 #include<stack>
  8 #include<bitset>
  9 #include<cstdlib>
 10 #include<cmath>
 11 #include<set>
 12 #include<list>
 13 #include<deque>
 14 #include<fstream>
 15 #include<math.h>
 16 #include<map>
 17 #include<queue>
 18 #include <iomanip>
 19 #include<stdio.h>
 20 using namespace std;
 21 const double PI=acos(-1.0);
 22 const double eps=1e-10;
 23 #define Max(a,b) (a)>(b)?(a):(b)
 24 #define Min(a,b) (a)<(b)?(a):(b)
 25 int s[400010],t[400010],n[400010],st[200010],num,nn,a[200010],F[200010],b,s0[400010],t0[400010],n0[400010],st0[200010],d[200010],ans;
 26 bool f[200010],ff[200010];
 27 void dfs(int now){
 28     f[now]=false;
 29     F[now]=num;
 30     int q=st[now];
 31     while (q!=-1){
 32         if ((f[t[q]])&&(a[now]==a[t[q]])){
 33             dfs(t[q]);
 34         }
 35         q=n[q];
 36     }
 37 }
 38 void dfs0(int now){
 39     f[now]=false;
 40     int q=st[now];
 41     while (q!=-1){
 42         if ((f[t[q]])&&(a[now]==a[t[q]])){
 43             dfs0(t[q]);
 44         }
 45         else{
 46             b++;
 47             s0[b]=F[now];
 48             t0[b]=F[t[q]];
 49             n0[b]=st0[F[now]];
 50             st0[F[now]]=b;
 51         }
 52         q=n[q];
 53     }
 54 }
 55 void bfs(){
 56     int q,now,tot,sos,ttt;
 57     d[1]=1;
 58     tot=1;
 59     sos=1;
 60     while (sos<=tot){
 61         ttt=tot;
 62         for (int i=sos;i<=tot;i++){
 63             now=d[i];
 64             ff[now]=false;
 65             q=st0[now];
 66             while (q!=-1){
 67                 if (ff[t0[q]]){
 68                     ttt++;
 69                     d[ttt]=t0[q];
 70                 }
 71                 q=n0[q];
 72             }
 73         }
 74         sos=tot+1;
 75         tot=ttt;
 76     }
 77     d[1]=d[ttt];
 78     tot=1;
 79     sos=1;
 80     ans=0;
 81     while (sos<=tot){
 82         ans++;
 83         ttt=tot;
 84         for (int i=sos;i<=tot;i++){
 85             now=d[i];
 86             ff[now]=true;
 87             q=st0[now];
 88             while (q!=-1){
 89                 if (!ff[t0[q]]){
 90                     ttt++;
 91                     d[ttt]=t0[q];
 92                 }
 93                 q=n0[q];
 94             }
 95         }
 96         sos=tot+1;
 97         tot=ttt;
 98     }
 99 }
100 int main(){
101     scanf("%d",&nn);
102     for (int i=1;i<=nn;i++){
103         scanf("%d",&a[i]);
104         f[i]=true;
105         st[i]=-1;
106     }
107     for (int i=1;i<nn;i++){
108         scanf("%d%d",&s[i*2-1],&t[i*2-1]);
109         s[i*2]=t[i*2-1];
110         t[i*2]=s[i*2-1];
111         n[i*2-1]=st[s[i*2-1]];
112         st[s[i*2-1]]=i*2-1;
113         n[i*2]=st[s[i*2]];
114         st[s[i*2]]=i*2;
115     }
116     num=0;
117     for (int i=1;i<=nn;i++){
118         if (f[i]){
119             num++;
120             dfs(i);
121         }
122     }
123     for (int i=1;i<=num;i++){
124         ff[i]=true;
125         st0[i]=-1;
126         b=0;
127     }
128     for (int i=1;i<=nn;i++){
129         if (!f[i]){
130             dfs0(i);
131         }
132     }
133     bfs();
134     printf("%d\n",ans/2);
135 }
Code by lucky_ji
技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 //#include<iostream>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 #include<string>
 9 #include<vector>
10 using namespace std;
11 #define INF 2000000000
12 #define Clear(x, Num) memset(x, Num, sizeof(x))
13 #define Dig(x) ((x>=‘0‘) && (x<=‘9‘))
14 #define Neg(x) (x==‘-‘)
15 #define G_c() getchar()
16 #define Maxe 400010
17 #define Maxn 200010
18 typedef long long ll;
19 
20 int n, Col[Maxn], From, Diameter, x, y;
21 int To[Maxe], Next[Maxe], Head[Maxe], Cnt;
22 
23 inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
24 inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
25 inline void Insert(int u, int v) { To[Cnt]=v; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
26 
27 inline void dfs(int u, int father, int depth)
28 {
29     if (depth>Diameter) From=u, Diameter=depth;
30     for (int p=Head[u]; p!=-1; p=Next[p])
31     {
32         int v=To[p];
33         if (v^father) dfs(v, u, depth+(Col[u]^Col[v]));
34     }
35 }
36 
37 int main()
38 {
39     Cnt=0; Clear(Head, -1);
40     read(n);
41     for (int i=1; i<=n; i++) read(Col[i]);
42     for (int i=1; i<n; i++) read(x), read(y), Insert(x, y), Insert(y, x);
43     dfs(1, -1, 1); Diameter=-1; dfs(From, -1, 1);
44     printf("%d\n", Diameter>>1);
45 }
Code by Return

 

F.Anton and School

Problems:构造序列a,满足如下性质,判断其是否合法并输出a

技术分享

Analysis:

  Return: 稍作观察即可发现b_i+c_i=a_i*n+a_1+a_2+..+a_n,令其为d_i, 从而可以求解出a_i=(d_i-(d_1+d_2+..+d_n)/(2*n))/n

       之后就是判断a_i是否合法了,不合法只有两种情况:1.a_i<0 2.由a_i反解出的b_i和c_i和原b_i和c_i不对应。

       对于后者,显然常规n^2构造会Time Limit Exceed,这时候回归题目,发现对于a_i在二进制下的第j位,可以统计该位在a_1..a_n中共有几个1,记为Sig_j,则b_i的计算为:当a_i第j位不为0时,由于对于该位来说,a_i执行&操作只有对a_1..a_n中该位同样为1的数有效,从而b_i=(Sig_j<<j),而a_i为0时,无论其他a在该位取何值,对该位的贡献仍然为0,同样可以推出c_i为(n<<j)//a_i第j位不为0,(Sig_j<<j)//a_i第j位为0,从而复杂度为O(nlog(Max_a_i_length))

Tags: Bitmasks, Math, Implementation

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 //#include<iostream>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 #include<string>
 9 #include<vector>
10 using namespace std;
11 #define INF 2000000000
12 #define Clear(x, Num) memset(x, Num, sizeof(x))
13 #define Dig(x) ((x>=‘0‘) && (x<=‘9‘))
14 #define Neg(x) (x==‘-‘)
15 #define G_c() getchar()
16 #define Maxn 200010
17 typedef long long ll;
18 
19 int n, b[Maxn], c[Maxn];
20 ll _b, _c, d[Maxn], a[Maxn], Sig, bit[Maxn][32], Sig_bit[32], Max;
21 
22 inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
23 inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
24 //inline void Insert(int u, int v) { To[Cnt]=v; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
25 
26 int main()
27 {
28     read(n);
29     for (int i=1; i<=n; i++) read(b[i]);
30     for (int i=1; i<=n; i++)
31     {
32         read(c[i]);
33         d[i]=(ll)b[i]+c[i], Sig+=d[i];
34     }
35     Sig/=(n<<1);
36     for (int i=1; i<=n; i++)
37     {
38         a[i]=(d[i]-Sig)/n;
39         if (a[i]<0) { puts("-1"); return 0; }
40         Max=max(Max, a[i]);
41     }
42     int Limit=(int)log2(Max); if ((1ll<<Limit)<Max) Limit++;
43     for (int i=1; i<=n; i++)
44         for (int j=0; j<=Limit; j++)
45             bit[i][j]=(a[i]&(1ll<<j)), Sig_bit[j]+=((bit[i][j])?(1):(0));
46     for (int i=1; i<=n; i++)
47     {
48         _b=_c=0;
49         for (int j=0; j<=Limit; j++)
50         {
51             ll Cur=(Sig_bit[j]<<j);
52             if (bit[i][j]) _b+=Cur, _c+=((ll)n<<j); else _c+=Cur;
53         }
54         if ((_b^b[i]) || (_c^c[i])) { puts("-1"); return 0; }
55     }
56     for (int i=1; i<n; i++) printf("%lld ", a[i]); printf("%lld\n", a[n]);
57 }
Code by Return

 

Codeforces Round #379 (Div. 2) Analyses By Team:Red & Black