Topic Link: Portal B-First-class bar
(Tree-Path compression)
Test Instructions: Give an n, indicating that there are N nodes 0~n,0 is the root node, and then give the number of n-1 to indicate that the parent node of node I nodes is given a Q, and then Q operations: R u v indicates the number of times the path between nodes u~v is accessed plus 1
Eg:5 0 1 1 3 W x indicates that you are asked to output the condition that the path is accessed between x and his parent node
5 If the output has not been accessed "Not yet"If the output is accessed more than 2 times"many times"
R 2 4 If only the path endpoint of the access was accessed once (Eg:Small end point)
W 3 (output: 2 4)Note: The output path endpoint is required when the output is accessed once (not necessarily he and its parent, try the left sample)
R 1 2
W 2 (output: many times)
W 1 (output: not yet)
Solution: The first access path, U,V, accesses +1 directly to all nodes in the path
If you access a path that was visited once, modify its pre value to its parent node
(Purpose: To compress the paths that are accessed to the second time, not to be accessed next time)
When accessing a path that has been visited twice, the end of the compressed path is obtained directly according to its pre-set (save time)
The code is as follows :
#include <cmath> #include <string> #include <cstring> #include <algorithm> #include <stdio.h
> #include <cmath> #include <iostream> using namespace std;
#define LL Long long #define INF 0x3f3f3f3f const int MAXN = 1e5 + 500; struct Node {int L, r;//record the path endpoint of the first access int dept;//Record the node's number of layers int FA;//record its parent node int cnt;//Count the number of accesses to the node (after path compression, median num max 2
)}TRE[MAXN];
int pre[maxn];//and check the operation of the tree operation more than 2 times the path compression processing int find (int x) {if (pre[x] = = x) return x;
return pre[x] = find (pre[x]); } void operation (int x, int y) {int u = x, v = y;//reserved U,v (because it happens to be "first-class edge") while (U! = V) {if (Tre[u]). Dept < tre[v].dept) Swap (U, v);
The depth of the first step forward operation (to ensure that they can meet) tre[u].cnt++;
if (tre[u].cnt = = 1) tre[u].l = min (x, y), TRE[U].R = max (x, y);
else pre[u] = TRE[U].FA;
U = Find (TRE[U].FA);
}} int main () {int n;
while (~SCANF ("%d", &n)) {for (int i = 1; i < n; i++) {scanf ("%d", &TRE[I].FA); Tre[i].dept = tre[tre[i].fa].dept+ 1;
tre[i].cnt = 0;
Pre[i] = i;
} int Q, u, v;
scanf ("%d", &q);
Char s[2];
while (q--) {scanf ("%s", &s);
if (s[0] = = ' R ') {scanf ("%d%d", &u, &v);
Operation (U, v);
} else {scanf ("%d", &u);
if (tre[u].cnt = = 0) printf ("Not yet\n");
else if (tre[u].cnt = = 1) printf ("%d%d\n", TRE[U].L, TRE[U].R);
else printf ("many times\n");
}}} return 0; }
E-youhane Assemblerti(KMP)
Test Instructions: Give an n, then give you n string (1~n), and then give you a Q, which indicates the Q-query, each time asked to give a u,v, ask to return the suffix string of the U-string and the prefix string of the V string the maximum number of matches (that is, the maximum number of identical)
Solution: The title guarantees that each file has only one set of data and the total string length of the data will not exceed 3e5, so each substring is very short, in fact, the violence can be passed (the field data is really violent, but I use the KMP) here KMP template directly return the answer to the question, do not know can learn one hand kmp.
The code is as follows:
#include <cmath> #include <cstdlib> #include <string> #include <cstring> #include <algorithm
> #include <stdio.h> #include <iostream> using namespace std;
#define LL Long Long const int MAXN = 3E5 + 500;
String S[MAXN];
int NXT[MAXN];
void Get_next (int y) {int len = s[y].length ();
int i = 0, j =-1;
Nxt[0] =-1;
while (I<len) {if (j = =-1 | | s[y][i] = = S[y][j]) {i++;
j + +;
Nxt[i] = j;
} else J = nxt[j];
}} int KMP (int x, int y) {int len1 = S[x].length (), len2 = S[y].length ();
int i = 0, j = 0;
Get_next (y);
while (I<LEN1) {if (j = =-1 | | s[x][i] = = S[y][j]) {i++;
j + +;
} else J = nxt[j];
} if (i = = len1) return j;
return 0;
} int main () {int n;
CIN >> N;
for (int i = 1; I <= n; i++) cin >> S[i];
int q,x,y;
CIN >> Q;
while (q--) {scanf ("%d%d", &x, &y);
if (x = = y) cout << s[x].length () << Endl; else cout << KMP (x, y) << Endl;
} return 0;
}
G-youhane as "Bang Riot"(Violence pruning)
Test Instructions: Give a N, followed by 2 lines, the first row n number of A[i], the second row n number represents b[i], the title want to output all A[i] and pay the lowest price, the cost formula is as follows so you can choose one output can also be output a few, only the last cost minimum value.
Solution : Positive solution I think is the slope optimization dp (I do not how) so this solution for the problem based on the data of the ingenious paper-cutting method, and then direct violence.
(because the data size of the topic a[i],b[i] is "0,1e3", so for cost analysis, when A[i] selects a single output, the maximum price is 1e6, ( defined here: Sum[i]=a[1]+...+a[i])) and then when sum[i]- sum[j]>2000, cost= (2e3-b[i]) ^2, with a minimum value of 1e6, is at the same cost as the maximum value of a single output, so this can be a break. (Of course, think about it, it seems that there is a bit of discrepancy, because the above is a single cost of 1e6, the following may be more than the cost of the number of output is 1e6, then 2000 can only be a card to the minimum value of the data, but fortunately 2000 of the tipping point on the AC, if not can be considered enlarged.
The code is as follows :
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
# include<algorithm>
#include <stdio.h>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <functional>
using namespace std;
#define LL Long long
#define INF 0x3f3f3f3f3f3f3f3f
const int MAXN = 1e6 +;
ll SUM[MAXN], B[MAXN], DP[MAXN];
int main () {
int n;
while (~SCANF ("%d", &n))
{for
(int i = 1; I <= n; i++)
{
scanf ("%lld", &sum[i]);
Sum[i] + = sum[i-1];
}
for (int i = 1; I <= n; i++)
scanf ("%lld", &b[i]);
for (int i = 1; I <= n; i++)
dp[i] = inf;
for (int i = 1, i <= N; i++)
{for
(int j = i-1; J >= 0; j--)
{
ll tmp = Sum[i]-sum[j];
IF (tmp >) break;
Dp[i] = min (Dp[i], Dp[j] + (Tmp-b[i]) * (Tmp-b[i]));
}
}
printf ("%lld\n", Dp[n]);
}
return 0;
}
H-symmetry and opposing claims
(Water problem)
Test Instructions : Give a n*n square a. Tectonic Phalanx B,c:
Make a = B + C. Where b is a symmetric matrix, and C is a matrix of objections.
For any element in the square s, if (s) ij = (s) Ji, then S is the symmetric matrix
For any element in the square T, if (t) ij =-(t) Ji, then T is the object-called matrix
Note that all operations are in the modulo m sense.
For each set of data, the anti-call matrix C is output in n rows;
If there is no solution, the output is "impossible";
If there are multiple solutions, the output of any solution.
Solution : The game did not pay attention to M is odd, so impossible situation is not exist, and B,C founder and take the value of arbitrary (meet the conditions) Therefore, we only need to draw a 2*2 on paper on the B,C founder add up can see a founder and B,c founder's contact, and C square on the left diagonal value are 0, other (Aij+aji)/2=bij=bji, and Cij=aij-bij or cij=-(aij-bij), so you can eliminate by a anyway B founder to get C founder value. Because the topic said all the data must be in the modulo operation%m, and we have in the process in addition to the 2 operation (so we foolishly wrote a wave of 2 inverse ac in the past, but the problem does not need 2 of the inverse, because M is odd, when (Aij+aji) is odd when the addition of a m can be)
Pay attention to the final output of C founder also%m
The code is as follows :
#include <cmath> #include <cstdlib> #include <algorithm> #include <iostream> using namespace std
;
#define LL Long long ll a[1500][1500];
int main () {ll n, mod;
while (~SCANF ("%lld%lld", &n, &mod)) {for (int i = 0; i < n; i++) for (int j = 0; J < N; j + +) {
scanf ("%lld", &a[i][j]);
if (i = = j) A[i][j] = 0;
A[I][J]%= mod;
} int flag = 0;
for (int i = 0, i < n; i++) for (int j = i; J < N; j + +) {ll tmp = A[i][j] + a[j][i];
if (tmp% 2 = 0) tmp + = mod;
TMP/= 2; A[I][J]-= tmp + mod; A[I][J]%= mod; A[I][J] + = mod;
A[I][J]%= mod; A[j][i]-= tmp + mod; A[j][i]%= mod; A[j][i] + = mod;
A[j][i]%= mod;
if ((a[i][j]+a[j][i])% mod! = 0) flag = 1;
} if (flag) cout << "Impossible" << Endl; else {for (int i = 0; i < n; i++) for (int j = 0; J < N; j + +) printf ("%lld%c", a[i][j], j = = n-1?
' \ n ': ');
}} return 0;
}
K-Pony Super Brine
(Binary enumeration method)
Test Instructions : Small Mago Cup brine, Cup has unit of Salt and unit of water. Pony is very bored, so he wants to know how many kinds of this cup of brine of non-empty set, pour together after the salt and water ratio is
Solution : Binary enumeration method, because it is to be able to combine all the circumstances, so for each cup of salt has only 2 states, take and not, but the n_max=35,2^35 operation must be timed out, so a twist and a half operation, for every n Cup of brine, we are divided into 2 parts, Each of the largest discussion cases is 2^18<1e6, so we can first deal with all the combinations of 2 parts, then select each data in a small part to do a binary search in the other data, and find the value of x/when the combination is satisfied. The number of Y can be time complexity O (NLOGN) (where n is the enumeration of all cases N, not the title N)
The code is as follows :
#include <cmath> #include <cstdlib> #include <string> #include <cstring> #include <algorithm
> #include <stdio.h> #include <cmath> #include <iostream> using namespace std;
#define LL Long Long const int MAXN = 3e5+500;
int n, TOP1, TOP2;
ll ans, xx, yy; struct Node {ll x, y;}
A[MAXN];
ll S1[MAXN], S2[MAXN];
void dfs1 (int i,ll x, ll y) {if (i = = N/2) {s1[top1++] = xx*y-yy*x;
Return
} DFS1 (i + 1, x, y);
DFS1 (i + 1, x + a[i].x, y + a[i].y);
} void dfs2 (int i,ll x, ll y) {if (i = = N) {s2[top2++] = yy*x-xx*y;
Return
} DFS2 (i + 1, x, y);
DFS2 (i + 1, x + a[i].x, y + a[i].y);
} int main () {int t;
scanf ("%d", &t);
while (t--) {scanf ("%d%lld%lld", &n, &xx, &yy);
for (int i = 0; i < n; i++) scanf ("%lld%lld", &a[i].x, &A[I].Y); TOP1 = 0;
DFS1 (0, 0, 0); TOP2 = 0;
DFS2 (N/2, 0, 0);
Ans = 0; x s1.x+s2.x//---=------------= x*s1.y+x*s2.y=y*s1.x+y*s2.x=> x*s1.y-y*s1.x = y*s2.x-x*s2.y//y s1.y+s2.y sort (s2, s2 + top2); for (int i = 0; i < top1; i++) ans + = (upper_bound (s2, s2 + top2, s1[i])-S2)-(Lower_bound (S2, s2 + top2, S1[i])
-S2);
cout << ans-1 << Endl;
} return 0; }