Codeforces Round #311 (Div. 2) A, B, C, D, E
A. Ilya and Diplomas
Train of Thought: I have a question. I just need to enumerate it and discuss the situation as soon as possible.
Code:
#include
#include
#include
#include #include
#include
#include
#define inf 1000000#define clr(x, y) memset(x, y, sizeof x)using namespace std;int rmina,rmaxa;int rminb,rmaxb;int rminc,rmaxc;int n;int main(){ scanf(%d, &n); scanf(%d%d%d%d%d%d, &rmina, &rmaxa, &rminb, &rmaxb, &rminc, &rmaxc); int d = n - rminb - rminc; if (d > rmaxa) { d = n - rmaxa - rminc; if (d > rmaxb) { d = n - rmaxa - rmaxb; printf(%d %d %d, rmaxa, rmaxb, d); } else printf(%d %d %d, rmaxa, d, rminc); } else printf(%d %d %d, d, rminb, rminc); return 0;}
B. Pasha and Tea
Question: there are a total of w liters of water, n boys and n girls. Each person has a cup with a capacity limit of a [I]. Each Boy has equal water capacity, and each girl has equal water capacity, and each boy has twice as much water as a girl, ask the maximum capacity that everyone can allocate to water.
Idea: set x to the amount of water allocated to each girl in the final state. a represents the minimum capacity of the girl, B represents the minimum capacity of the boy, and x = min (, b/2, w/3 * n), then ans = x * 3 * n
Code:
#include
#include
#include #include
#include
#include
#define clr(x, y) memset(x, y, sizeof x)#define inf 1000000000using namespace std;const int maxn = 300005;int a[maxn];int n, w;int main(){ scanf(%d%d, &n, &w); for (int i = 0; i < 2*n; i++) scanf(%d, &a[i]); sort(a, a + 2*n); double x0 = (double)w / (3*n); double x1 = (double)a[0]; double x2 = (double)a[n] / 2; x0 = min(x0, x1); x0 = min(x0, x2); x0 = x0 * 3 * n; printf(%f, x0); return 0;}
C. Arthur and Table
Question: Give a table with n legs, each leg has its length li, and remove a leg to consume di energy, when the number of legs with the maximum length is greater than the total number of legs, the table is in a stable State. Input n, li, di asked the minimum amount of energy required to turn the table into a stable State.
Thought: At first glance, it seems that it is necessary to enumerate the maximum length of the table leg, but how can we quickly calculate the amount of energy required to reach a stable State after the table leg? This energy consists of two parts. One part is to delete all the required energy from the legs with a length greater than the ones currently being enumerated, one part is to delete the amount of energy required to make the enumerated length of the table leg more than half. At first, I put all my attention on a single table, and then I felt that it would time out when calculating the complexity, later I noticed that the key ------- di of the question is only 200 in size. I can classify the table and feet according to di, and then enumerate di from small to large. The problem is solved ~~
Code:
#include
#include
#include #include
#include
#include
#define clr(x, y) memset(x, y, sizeof x)#define inf 1000000000using namespace std;const int maxn = 100005;int n;int L[maxn];int D[maxn];int sum[maxn];int cnt[maxn];int cnt_d[maxn];struct pp{ int li, di; pp(int a = 0, int b = 0) : li(a), di(b) {}} P[maxn];bool cmp(pp A, pp B){ return A.li > B.li;}int main(){ scanf(%d, &n); for (int i = 0; i < n; i++) scanf(%d, &L[i]); for (int i = 0; i < n; i++) scanf(%d, &D[i]); for (int i = 0; i < n; i++) P[i] = pp(L[i],D[i]); clr(sum, 0); clr(cnt, 0); clr(cnt_d, 0); for (int i = 0; i < n; i++) { sum[L[i]] += D[i]; cnt[L[i]] ++; cnt_d[D[i]] ++; } sort(P, P + n, cmp); int coa, ss, cnta, ans; coa = 0; cnta = 0; ans = inf; for (int i = 0; i < n; i++) { ss = coa; int v = P[i].li; int j; for (j = i; j < n; j++) { if (P[j].li != v) break; cnt_d[P[j].di]--; } i = j-1; int nn = n - cnta; int cha; if (cnt[v] == 1) cha = nn - 1; else cha = nn - (cnt[v] - 1) * 2 - 1; for (int i = 1; i <= 200; i++) { if (cha > cnt_d[i]) { ss += cnt_d[i] * i; cha -= cnt_d[i]; } else { if (cha >= 0) ss += i * cha; break; } } ans = min(ans, ss); cnta += cnt[v]; coa += sum[v]; } printf(%d, ans); return 0;}
D. Vitaly and Cycle
Question: Give an undirected graph (the graph may not be connected) and ask how many sides are added at least to make the graph have a strange ring and calculate the number of edge adding methods.
Train of Thought: the question is not very difficult, but it took a long time to grind the question. The practice is as follows: First of all, there is a fact that everyone understands: the number of edges to be added to a ring cannot exceed 3, and then we will discuss the situation of adding 0, 1, 2, and 3 edges in detail.
First, perform black and white dyeing on the graph, and calculate the number of black nodes and the number of white nodes in each connected block.
Case 0: If a Unicom block does not succeed in black and white dyeing, there must be a strange ring. In this Case, the number of edges to be added is 0, and the number of solutions is fixed to 1. (If the two sides of an edge have the same color, the dyeing will fail)
Case 1: For a Unicom block, if two black or white points are connected with one side, a ring can be formed, therefore, you can quickly calculate the number of black and white nodes in each Unicom block.
Case 2: If each connected block is one or two vertices, two edges can form a ring, in this way, we can count the number of connected blocks of the next vertex and the number of connected blocks of the two vertices, and then use the combined math to get involved.
Case 3: all are independent vertices. You can set three vertices as needed ~~~
Ps: black and white dyeing is actually a direct run of dfs (or bfs). I ran a spanning tree when I was too young, and then dyed it. In fact, it is not necessary ~.
Code:
#include
#include
#include #include
#include
#include
#define clr(x, y) memset(x, y, sizeof x)#define inf 1000000000using namespace std;const int maxn = 200005;vector
G[maxn];struct edge{ int st,ed; bool flag;} E[maxn];int n, m;int par[maxn];int col[maxn];int white[maxn];int black[maxn];int ta;void init(int n_){ for(int i = 0; i <= n_; i++) par[i] = i;}int Find(int x){ if (x == par[x]) return x; return par[x] = Find(par[x]);}void unit(int x, int y){ x = Find(x); y = Find(y); if (x == y) return ; par[y] = x;}bool same(int x, int y){ return Find(x) == Find(y);}void dfs(int u, int &wh, int &bl){ for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (col[v] != -1) continue; col[v] = col[u]^1; col[v] == 0? wh++ : bl++; dfs(v, wh, bl); }}int main(){ scanf(%d%d, &n, &m); int st, ed; for (int i = 0; i < m; i++) { scanf(%d%d, &E[i].st, &E[i].ed); E[i].flag = false; } init(n); for (int i = 0; i < m; i++) { if (!same(E[i].st, E[i].ed)) { unit(E[i].st, E[i].ed); G[E[i].st].push_back(E[i].ed); G[E[i].ed].push_back(E[i].st); E[i].flag = true; } } clr(col, -1); clr(white, 0); clr(black, 0); ta = 0; for (int i = 1; i <= n; i++) { if (col[i] == -1) { int wh = 1; int bl = 0; col[i] = 0; dfs(i, wh, bl); white[ta] = wh; black[ta++] = bl; } } for (int i = 0; i < m; i++) { if (E[i].flag == true) continue; if (col[E[i].st] == col[E[i].ed]) { printf(0 1); return 0; } } long long w = 0; for (int i = 0; i < ta; i++) { if (white[i] > 1) w += (long long)white[i]*(white[i]-1)/2; if (black[i] > 1) w += (long long)black[i]*(black[i]-1)/2; } if (w > 0) { printf(1 %lld, w); return 0; } int cnt = 0; int tmp = n; for (int i = 0; i < ta; i++) { if (white[i]+black[i] > 1) cnt++; } for (int i = 0; i < ta; i++) { if (white[i]+black[i] > 1) { cnt--; tmp -= 2; w += tmp; w += 2*cnt; } else { tmp --; w += cnt; } } if (w > 0) { printf(2 %lld, w); return 0; } w += (long long)n*(n-1)*(n-2)/6; printf(3 %lld, w); return 0;}
E. Ann and Half-Palindrome
Question: first, the question defines a semi-return string: A string is a semi-return string. if and only, the characters at the odd position on the left of the center axis are the same as those at the symmetric position, the question shows a string s, and an integer k. You can find the k-th largest string in the Lexicographic Order of all the semi-return substrings of s. The length of s is 5000.
Train of Thought: This question is also full of twists and turns. When I first heard liu shen say it was violent, I tried one of the most violent practices, Nima Ah O (n ^ 3) you may not be afraid of this method. If it is time-out, you may be wondering how to optimize it. I feel that there is nothing to optimize in the enumerated substrings, I was wondering if there was any faster method for returning the text. I didn't think of it (or it was too weak ), then Liu Shen told me to use the interval dp idea to pre-process it at will. Then, I suddenly realized that I was about to change it again and found that the memory was too large-> ___->, then, Liu told me to use a dynamic dictionary tree. Then I changed the dictionary tree and found that T had ~~~~, When Liu's posture is viewed, he finds that the dictionary tree is inserted with O (n), but if he does not insert one, it is equivalent to inserting all the prefixes starting with the inserted string, therefore, only the enumeration header can be used to enumerate substrings ~~~, I changed it to the last one...
Each node in the dictionary tree maintains one more domain for storage, and the number of semi-return strings in its subtree, then, find the K-th string and use the idea similar to the dfs on the Balance Tree to find a node to constantly search for the left and right subtree. There are some small details to pay attention ~~~
Code:
# Include
# Include
# Include
# Include
# Include
# Define clr (x, y) memset (x, y, sizeof x) # define inf 1000000000 using namespace std; string s; int k; vector
Vv; int dp [5005] [5005]; int dfs (int I, int j) {if (I = j) return dp [I] [j] = 1; if (j <I) return dp [I] [j] = 1; if (dp [I] [j]! =-1) return dp [I] [j]; if (dfs (I + 2, J-2) & s [I] = s [j]) return dp [I] [j] = 1; return dp [I] [j] = 0;} class Trie {public: int flag; int num; trie * next [2]; Trie () {flag = 0; num = 0; next [0] = next [1] = 0 ;}} * root; int dfs (Trie * p) {if (! P) return 0; p-> num + = p-> flag; p-> num + = dfs (p-> next [0]); p-> num + = dfs (p-> next [1]); return p-> num;} string solve (Trie * p, int k) {Trie * lson = p-> next [0], * rson = p-> next [1]; int lnum, rnum; if (lson = 0) lnum = 0; else lnum = lson-> num; if (rson = 0) rnum = 0; else rnum = rson-> num; if (p-> flag> = k) return; else if (lnum + p-> flag> = k) return a + solve (lson, k-p-> flag ); else return B + sol Ve (rson, k-lnum-p-> flag);} void Trie_insert (int st, int ed) {Trie * p = root; for (int I = st; I <ed; I ++) {int index; if (s [I] = 'A') index = 0; else index = 1; if (! P-> next [index]) {p-> next [index] = new Trie;} p = p-> next [index]; if (dfs (st, I )) p-> flag ++;} int main () {cin> s> k; int len = s. length (); clr (dp,-1); root = new Trie (); for (int I = 0; I <len; I ++) {Trie_insert (I, len);} dfs (root); cout <solve (root, k) <
After completing a question, add yourself an oil ~~