Codeforces Round #353 (Div. 2) ABCDE 题解 python
Posted 我是阿格斯之盾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #353 (Div. 2) ABCDE 题解 python相关的知识,希望对你有一定的参考价值。
# | Name | ||
---|---|---|---|
A |
standard input/output
1 s, 256 MB |
x3509 | |
B |
standard input/output
1 s, 256 MB |
x2519 | |
C |
standard input/output
1 s, 256 MB |
x724 | |
D |
standard input/output
2 s, 256 MB |
x1008 | |
E |
standard input/output
2 s, 256 MB |
x239 |
以后cf的题能用python写的我就python了,因为以后没正式比赛参加了,不必特地用C++。python写得快,也容易看得懂,我最近也比较需要练习这个。当然有的题C++写得少我还是用C++。
A. Infinite Sequence
题意:给出a,b,c,求是否a加若干个c能得到b,是就输出YES,否就输出NO
题解:
就特判各种情况,一般情况是看(b-a)%c==0
特殊情况,依次判断:
1.a==b,YES
2.c==0,NO
3.b-a与c不同号,NO
4.c小于零,则把b-a和c都变正数再判。
1 def gank(a,b,c): 2 d = b - a 3 if(d==0): 4 return True 5 if(c==0): 6 return False 7 if((d<0 and c>0) or(c<0 and d>0)): 8 return False 9 if(c<0): 10 d*=-1 11 c*=-1 12 if(d%c==0): 13 return True 14 else: 15 return False 16 17 a,b,c = map(int , raw_input().split(\' \')) 18 if(gank(a,b,c)): 19 print "YES" 20 else: 21 print "NO"
B. Restoring Painting
题意:有个3*3的九宫格,每个格子能填1~n中任意的数(n由输入给出)。要求其中任意2*2的格子中4个数的和与其他各个2*2格子都相等。
输入n,a,b,c,d,求剩下的数有多少种填法。(可能为0种)
题解:
固定中间的为1,则4种2*2格子的和,要是使得一个相邻的数比较大的角为1,另一个相邻数字比较小的角为n,格子和也没法相等的话,就不行,所以要找2*2格子的最小值和最大值,判断可行性。
比如有这种情况,最大那个角填1,最小那个角最少只能填x,则它们有(n-x+1)种情况(最小的那个角为x,为x+1,直到为n)。
中间那个数其实随便填,不影响,所以最后答案(n-x+1)*n
1 def gank(n,A,b,c,d): 2 a = [0]*4 3 a[0] = A+b 4 a[1] = A+c 5 a[2] = b+d 6 a[3] = c+d 7 mi = 1e9 8 ma = 0 9 for i in range(4): 10 ma = max(ma,a[i]) 11 mi = min(mi,a[i]) 12 if(1 + 1 + ma > 1+n+mi): 13 return 0 14 x = ma - mi + 1 15 y = n - x + 1 16 return y*n 17 18 19 n,a,b,c,d = map(int , raw_input().split(\' \')) 20 print gank(n,a,b,c,d)
C. Money Transfers
题意:
有一圈银行,瓦夏在各个银行存的钱为a[i](可能为负数,代表借了钱),sum(a[i])==0,瓦夏可以进行一种操作:把一个银行的若干钱转到相邻的银行。求最少多少次操作能把所有银行存款归零。
题解:
这题,难!过D的人都比过C的多,我是不会的,看的题解。
首先考虑,若有一个区间[L,R],使得其中的sum(a[i])==0,则这个区间可以单独转钱就能归零,用的操作数为R-L。如果一个银行为0,它可以单独当一个区间。最后,我们可以得到若干个相邻的区间,总操作数为(n - 区间数)。
所以问题转化为最大化这种区间数。
为了找到和为0的区间,我们算一波前缀和。
当有两个位置的前缀和相同,说明这两个之间的各个元素和为0!
当很多个位置的前缀和相同,说明这些位置分成的各个区间,每个区间和为0。
我们就算一波各个前缀和出现的次数,出现次数最多的那个就是按照最碉的分区间法得到的最多区间数。
1 def farm(n, a): 2 dic = dict() 3 re=0 4 sum = 0 5 for i in a: 6 sum += i 7 if not sum in dic: 8 dic[sum]=0 9 dic[sum]+=1 10 re = max(re,dic[sum]) 11 return n - re 12 13 n = input() 14 a = map(int, raw_input().split(\' \')) 15 ans = farm(n, a) 16 print ans
D. Tree Construction
题意:给出一个各不相同的序列,插入二叉搜索树中,二叉搜索树不作平衡处理,直接强插,输出除了第一个点之外各个点的父亲的值。
题解:
直接强插,O(n^2),会爆。我不懂,我又看的题解会的。
这个朴素二叉搜索树的特性,是我要插x,那它肯定要成为之前插入过的数中比它小的中最大的数的右儿子 或者 比它大的数中最小的数的左儿子。
所以我们就找用别的平衡树找到这2个数在朴素树中的位置。然后根据性质,肯定只有一个地方能插,我们就插。(可恶,我不懂为什么,对这个树的性质理解不完全)
可以用C++的STL的set和map来当平衡树,我就用C++写了。
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 14 #define MZ(array) memset(array, 0, sizeof(array)) 15 #define MF1(array) memset(array, -1, sizeof(array)) 16 #define MINF(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define FORD(i,x,y) for(i=(x);i>=(y);i--) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define WN(x) printf("%d\\n",x); 24 #define RE freopen("D.in","r",stdin) 25 #define WE freopen("huzhi.txt","w",stdout) 26 #define MP make_pair 27 #define PB push_back 28 #define PF push_front 29 #define PPF pop_front 30 #define PPB pop_back 31 template<class T>inline void OA(const T &a,const int &st,const int &ed) { 32 if(ed>=st)cout<<a[st]; 33 int i; 34 FOR(i,st+1,ed)cout<<\' \'<<a[i]; 35 puts(""); 36 } 37 typedef long long LL; 38 typedef unsigned long long ULL; 39 40 const double PI=acos(-1.0); 41 const double EPS=1e-10; 42 const int MAXN=111111; 43 const int MAXM=33; 44 45 struct Node { 46 int value; 47 Node *son[2]; 48 Node() {} 49 Node(int v) { 50 value = v; 51 son[0]=son[1]=NULL; 52 } 53 } root; 54 55 typedef pair<int, Node*> PIN; 56 set<PIN> s; 57 int n; 58 int a[MAXN]; 59 int ans[MAXN]; 60 61 void farm() { 62 root = Node(a[0]); 63 s.clear(); 64 s.insert(MP(a[0], &root)); 65 int i; 66 FOR(i,1,n-1) { 67 set<PIN>::iterator it = s.upper_bound(MP(a[i],(Node*)NULL)); 68 if(it!=s.end() and it->second->son[0]==NULL) { 69 (it->second)->son[0] = new Node(a[i]); 70 s.insert(MP(a[i], it->second->son[0])); 71 ans[i] = it->second->value; 72 } else { 73 set<PIN>::iterator it2 = it; 74 if(it2!=s.begin())it2--; 75 it2->second->son[1] = new Node(a[i]); 76 s.insert(MP(a[i], it2->second->son[1])); 77 ans[i] = it2->second->value; 78 } 79 80 } 81 } 82 83 84 int main() { 85 int i; 86 RD(n); 87 REP(i,n)RD(a[i]); 88 farm(); 89 OA(ans,1,n-1); 90 return 0; 91 }
E. Trains and Statistic
题意:有一个一条直线的地铁线路。给出a数组,每个站点i只能买到去往[i+1, a[i]]内的票。设p(i,j)为从i到j所需要的最少票数,求对所有ij的p(i,j)的和。(1=<i<j<=n)
题解:
设f[x]为从站点x到它之后所有站点票数的和。
简单设想,f[x]的值对f[x-1] f[x-2]等等各个值的计算是有用的。
当从一个站点i到不了所有点时,会到它能到的点中a[i]最大的点x。这时就能用到f[x]。
b[i] = x-i + b[x] + n - a[i]
其中自己能走i+1~x-1点,用x-i票。
x能到x+1~n,用b[x]票。
x能走的那些中,x+1 ~ a[i]是i自己能走的,把x走的当做自己走的,更远的要自己买票走到x,要n - a[i]张票。
综合起来就是上面那个公式。
x能走的肯定比a[i]远,因为a[a[i]]肯定要大于a[i]。
这样,我们要做的就是每次找出区间[i+1, a[i]]中a[x]最大的x。
这可以用各种RMQ方法。不能用单调区间O(1)求,因为这个区间不是纯粹向左移动的,左界是一个个往左,右界是会来回动的。
所以我们可以维护一个只进不出的单调下降队列,然后用二分找。
O(nlogn)
1 from collections import deque 2 3 def argmax(q,z): 4 l = 0 5 r = len(q) - 1 6 while(l<=r): 7 mid = (l+r)/2 8 x = q[mid][\'i\'] 9 if(x<=z): 10 r = mid - 1 11 else: 12 l = mid + 1 13 return q[l][\'i\'] 14 15 def gank(n,A): 16 a = [0]*(n+1) 17 a[1:] = A 18 b = [0]*(n+1) 19 b[n-1] = 1 20 q = deque() 21 q.append({\'i\':n-1, \'a\':a[n-1]}) 22 for i in range(n-2, 0, -1): 23 if(a[i]>=n): 24 b[i] = n-i 25 else: 26 x = argmax(q,a[i]) 27 b[i] = x-i + b[x] + n - a[i] 28 while(len(q)>0 and q[-1][\'a\'] < a[i]): 29 q.pop() 30 q.append({\'i\':i, \'a\':a[i]}) 31 return sum(b) 32 33 n = int(raw_input()) 34 a = map(int , raw_input().split(\' \')) 35 print gank(n,a)
以上是关于Codeforces Round #353 (Div. 2) ABCDE 题解 python的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #353 (Div. 2) A. Infinite Sequence
[Codeforces] Round #353 (Div. 2)
Codeforces Round #353 (Div. 2) A. Infinite Sequence 思维题
Codeforces Round #353 (Div. 2) ABCDE 题解 python
Codeforces Round #353 (Div. 2)
Codeforces Round #353 (Div. 2) B. Restoring Painting __ map or set 思维题