Question Link

A. Yaroslav and Permutations

Question:

An array of n elements. Each element cannot exceed 1000. Two adjacent elements can be exchanged and the values of the two adjacent elements can be changed after a limited number of operations.

#include <stdio.h>#include <string.h>int cnt[1005];int main(){ int n, a; while (scanf("%d", &n) != EOF) { memset(cnt, 0, sizeof(cnt)); for (int i = 0; i < n; i++) { scanf("%d",&a); cnt[a]++; } int m = -1; for (int i = 0; i <= 1000;i++) { if (cnt[i] > m) m = cnt[i]; } if (n%2 == 0) { if (m > (n/2)) puts("NO"); else puts("YES"); } else { if (m > (n/2+1)) puts("NO"); else puts("YES"); } } return 0;}

B. Yaroslav and two strings (reproduced in the original article)

For the two strings separator and CH2, open four arrays A [I], B [I], C [I], d [I] indicates the number of all conditions, the number of conditions [I] <= CH2 [I], the number of conditions [I]> = CH2 [I], and the number of conditions [I] = CH2 [I, according to the review principle, ANS = Radia [I]-effecb [I]-effecc [I] + effecd [I].

Code

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <set>#include <map>#include <cmath>#include <queue>using namespace std;template <class T> void checkmin(T &t,T x) {if(x < t) t = x;}template <class T> void checkmax(T &t,T x) {if(x > t) t = x;}template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;}template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;}typedef pair <int,int> PII;typedef pair <double,double> PDD;typedef long long ll;#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++)#define MOD 1000000007int n ;ll a[101000] , b[101000] , c[101000] , d[101000];char ch1[101000] , ch2[101000];void gcd(ll a , ll b , ll &d , ll &x , ll &y) { if(!b) {d = a; x = 1; y = 0;} else { gcd(b , a%b,d,y , x); y -= x * (a/b); }}ll inv(ll a , ll n) { ll d , x , y; gcd(a , n , d, x , y); return d == 1 ? (x+n)%n : -1;}void debug() { for(int i=0;i<n;i++) cout << a[i] << " "; cout << endl; for(int i=0;i<n;i++) cout << b[i] << " "; cout << endl; for(int i=0;i<n;i++) cout << c[i] << " "; cout << endl; for(int i=0;i<n;i++) cout << d[i] << " "; cout << endl;}int main() { cin >> n; scanf("%s%s",ch1,ch2); for(int i=0;i<n;i++) { if(ch1[i] == '?' && ch2[i] == '?') { a[i] = b[i] = 55;c[i] = 10; d[i] = 100; } else if(ch1[i] == '?') { a[i] = ch2[i] - '0'+1; b[i] = 11-a[i]; c[i] = 1; d[i] = 10; } else if(ch2[i] == '?') { b[i] = ch1[i] - '0'+1; a[i] = 11-b[i]; c[i] = 1; d[i] = 10; } else { if(ch1[i] <= ch2[i]) a[i] = 1; if(ch1[i] >= ch2[i]) b[i] = 1; if(ch1[i] == ch2[i]) c[i] = 1; d[i] = 1; } } ll a1 = 1 , a2 = 1 , a3 = 1 , a4 = 1; for(int i=0;i<n;i++) { a1 *= a[i]; a1 %= MOD; a2 *= b[i]; a2 %= MOD; a3 *= c[i]; a3 %= MOD; a4 *= d[i]; a4 %= MOD; } ll ans = (a4-a1-a2+a3) % MOD; if(ans < 0) ans += MOD; cout << ans << endl; //debug(); return 0;}

C. Greg and array

Question:

An array of N numbers, and then M groups, each operation is to add the value of each element from L to R to V, then K groups of operations, each group indicates executing the x, x + 1 ...... Group Y operation, and then output array elements.

Ideas:

For the problem of interval modification, there is no doubt that the line segment tree is used, but there are two line segment trees. However, here we only build on the array, instead of building on the number of operations, we use the lazy idea, we can more easily know how many operations are performed in the group, and then update the line segment tree. The updated Val value is the original V of the Operation multiplied by the number of operations.

Code:

# Include <stdio. h> # include <string. h> typedef _ int64 ll; const ll maxn = 100005; ll a [maxn]; struct node {ll l, R, M; ll sum, mark ;} tree [maxn <2]; ll CNT [maxn]; struct operation {ll l, R, V;} op [maxn]; void build (ll l, ll R, ll o) {tree [O]. L = L; tree [O]. R = r; ll M = (L + r)> 1; tree [O]. M = m; tree [O]. mark = 0; If (L = r) {tree [O]. sum = A [l]; return;} build (L, M, O <1); Build (m + 1, R, (O <1) + 1 ); tree [O]. Sum = tree [O <1]. sum + tree [(o <1) + 1]. SUM;} void Update (ll l, ll R, ll V, ll o) {If (tree [O]. L = L & tree [O]. R = r) {tree [O]. mark + = V; return;} tree [O]. sum + = (LL) (R-l + 1) * V; If (tree [O]. m> = r) Update (L, R, V, O <1); else if (L> tree [O]. m) Update (L, R, V, (O <1) + 1); else {Update (L, tree [O]. m, V, O <1); Update (tree [O]. m + 1, R, V, (O <1) + 1) ;}} ll query (ll l, ll R, ll o) {If (tree [O]. L = L & tree [O]. R = r) return tree [O]. sum + tree [O]. mark * (R-l + 1); If (tree [O]. mark! = 0) {tree [O <1]. mark + = tree [O]. mark; tree [(o <1) + 1]. mark + = tree [O]. mark; tree [O]. sum + = (LL) (tree [O]. r-tree [O]. L + 1) * tree [O]. mark; tree [O]. mark = 0;} If (tree [O]. m> = r) return query (L, R, O <1); else if (tree [O]. m <L) return query (L, R, (O <1) + 1); else return query (L, tree [O]. m, O <1) + query (tree [O]. m + 1, R, (O <1) + 1);} int main () {ll n, m, K, L, R, X; while (scanf ("% i64d % i64d % i64d", & N, & M, & K )! = EOF) {for (ll I = 1; I <= N; I ++) scanf ("% i64d", & A [I]); Build (1, n, 1); For (ll I = 1; I <= m; I ++) scanf ("% i64d % i64d % i64d", & OP [I]. l, & OP [I]. r, & OP [I]. v); memset (CNT, 0, sizeof (CNT); For (ll I = 1; I <= K; I ++) {scanf ("% i64d % i64d", & L, & R); CNT [l] + = 1; CNT [R + 1]-= 1 ;} ll sum = 0; For (ll I = 1; I <= m; I ++) {sum + = CNT [I]; // lazy's idea Update (OP [I]. l, OP [I]. r, sum * op [I]. v, 1) ;}for (ll I = 1; I <n; I ++) printf ("% i64d", query (I, I, 1 )); printf ("% i64d \ n", query (N, N, 1);} return 0 ;}

D. Greg and graph (reproduced in the original article)

Before talking about this question, I will briefly introduce the Floyd-warshall algorithm to help you better understand this question.

The principle of the Floyd-warshall algorithm is dynamic planning.

If d [I] [J] [k] is set from I to J, only 1 ~ If the node in K is the shortest path length of the intermediate node, then:

(1) If the shortest path goes through vertex K, so d [I] [J] [k] = d [I] [k] [k-1] + d [k] [J] [k-1]

(2) If the shortest path does not go through vertex K, then d [I] [J] [k] = d [I] [J] [k-1]

Therefore, d [I] [J] [k] = min (d [I] [k] [k-1] + d [k] [J] [k-1], d [I] [J] [k] = d [I] [J] [k-1]).

If we put K in the loop of the outermost layer, the third bit can be omitted in implementation.

This question can be reversed. If we consider adding one point one by one, then the answer will be output.

Each point we add is equivalent to K. First we need to carry out a double loop to find the shortest path between K and all points; then we can judge the K-1 points before the node is updated by K, the time complexity is reduced to O (N ^ 3), and the brute-force solution performs Floyd every time. The time complexity is O (n ^ 4). In contrast, the aforementioned solution considers the nature of the Floyd algorithm, it makes better use of the internal quality of the algorithm.

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <set>#include <map>#include <cmath>#include <queue>using namespace std;template <class T> void checkmin(T &t,T x) {if(x < t) t = x;}template <class T> void checkmax(T &t,T x) {if(x > t) t = x;}template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;}template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;}typedef pair <int,int> PII;typedef pair <double,double> PDD;typedef long long ll;#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++)int n ;const int N = 555;int g[N][N];ll ans[N];int a[N];int main() { cin >> n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin >> g[i][j]; for(int i=n;i>=1;i--) cin >> a[i]; ans[1] = 0; for(int i=2;i<=n;i++) { int aa = a[i]; ans[i] += ans[i-1]; for(int j=1;j<i;j++) ans[i] += g[a[i]][a[j]] + g[a[j]][a[i]]; for(int j=1;j<i;j++) for(int k=1;k<i;k++) { if(g[a[j]][a[i]] > g[a[j]][a[k]]+g[a[k]][a[i]]) { ans[i] -= g[a[j]][a[i]]; ans[i] += g[a[j]][a[k]]+g[a[k]][a[i]]; g[a[j]][a[i]] = g[a[j]][a[k]]+g[a[k]][a[i]]; } if(g[a[i]][a[j]] > g[a[i]][a[k]] + g[a[k]][a[j]]) { ans[i] -= g[a[i]][a[j]]; ans[i] += g[a[i]][a[k]] + g[a[k]][a[j]]; g[a[i]][a[j]] = g[a[i]][a[k]] + g[a[k]][a[j]]; } } for(int j=1;j<i;j++) for(int k=1;k<i;k++) { if(g[a[j]][a[k]] > g[a[j]][a[i]] + g[a[i]][a[k]]) { ans[i] -= g[a[j]][a[k]]; ans[i] += g[a[j]][a[i]] + g[a[i]][a[k]]; g[a[j]][a[k]] = g[a[j]][a[i]] + g[a[i]][a[k]]; } } } cout << ans[n]; for(int i=n-1;i>=1;i--) cout << " "<< ans[i]; cout << endl; return 0;}