Codeforces Round #379 (Div. 2) Analyses By Team:Red & Black
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #379 (Div. 2) Analyses By Team:Red & Black相关的知识,希望对你有一定的参考价值。
Problems: 给你长度为N的,只含‘A’,‘D‘的序列,统计并输出何者出现的较多,相同为"Friendship"
Analysis:
lucky_ji: 水题,模拟统计A和D的数目比较大小输出结果即可
Tags: Implementation
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
Problems: 给定n个单位,每个单位花费为x,同时给定初始魔法值s,有两种咒语,每种至多使用一个,第一类有m个,消耗d_i,可以让所有单位花费变为a_i,第二类有k个,消耗d_i, 可以让c_i个单位花费变为0,求最小总花费。输入保证c_i, d_i单调递增
Analysis:
lucky_ji: 2类药剂代价和效果输入均满足不递减,故可以用二分搜索 首先先把单用一种药剂的最小代价求出,对于每一种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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
以上是关于Codeforces Round #379 (Div. 2) Analyses By Team:Red & Black的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #370 - #379 (Div. 2)
Codeforces Round #379 (Div. 2) D. Anton and Chess(模拟)
Codeforces Round #379 (Div. 2)
Codeforces Round #379 (Div. 2) 总结分享
Codeforces Round #379 (Div. 2) C. Anton and Making Potions(二分)