# 2018年全国多校算法寒假训练营练习比赛（第五场）解题报告

## A-逆序数

https://www.nowcoder.com/acm/contest/77/A

#### 输出描述:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5+10;
int arr[maxn], tmp[maxn];
long long ans;

void merge(int *a, int st, int mid, int ed) {
int i = st, j = mid + 1, k = st;
while (i <= mid && j <= ed) {
if (a[i] <= a[j]) {
tmp[k++] = a[i++];
} else {
ans += j - k;
tmp[k++] = a[j++];
}
}

while (i <= mid) {
tmp[k++] = a[i++];
}
while (j <= ed) {
tmp[k++] = a[j++];
}
for (int i = st; i <= ed; i++) {
a[i] = tmp[i];
}
}

void merge_sort(int *a, int st, int ed) {
if (st < ed) {
int mid = (st+ed) / 2;
merge_sort(a, st, mid);
merge_sort(a, mid+1, ed);
merge(a, st, mid, ed);
}
}

int main(void) {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
merge_sort(arr, 0, n-1);
cout << ans << endl;
} 

## B-Big Water Problem

#### 题目描述

1：给定两个整数x, y, 然后在原数组的第x位置上加y；
2：给定两个整数l，r，然后输出数组从第l位加到第r位数字的和并换行

#### 输出描述:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
int tree[maxn<<2];

inline void pushUp(int node) {
tree[node] = tree[node<<1] + tree[node<<1|1];
}

void build(int node, int l, int r) {
if (l == r) cin >> tree[node];
else {
build(node<<1, l, (l+r) / 2);
build((node<<1) +1, (l+r) / 2 + 1, r);

pushUp(node);
}
}

void updata(int l, int r, int node, int index, int num) {
if (l == r) {
tree[node] += num;
return;
}
int mid = (l+r) >> 1;
if (index <= mid)  updata(l, mid, node << 1, index, num);
else updata(mid+1, r, (node << 1)+1, index, num);
pushUp(node);
}

int query(int node, int l, int r, int i, int j) {
if (i <= l && j >= r) return tree[node];
int mid = (l+r) >> 1, sum = 0;
if (i <= mid) sum += query(node<<1, l, mid, i, j);
if (j > mid) sum += query(node<<1|1, mid+1, r, i, j);
return sum;
}

int main(void) {
ios::sync_with_stdio(0);

int n, m;
cin >> n >> m;

build(1, 1, n);
while (m--) {
int a, b, op;
cin >> op >> a >> b;
if (op == 2)
cout << query(1, 1, n, a, b) << endl;
else
updata(1, n, 1, a, b);
}
return 0;
}

## C-字符串的问题

#### 输出描述:

#include <bits/stdc++.h>
using namespace std;

string s;
string pre, suf, mid, ans = "Just a legend";
int main(void) {
cin >> s;
int len = s.size();
if (len < 3) {
puts("Just a legend");
return 0;
}
int k = 0;
while (++k < len) {
pre = s.substr(0, k);
suf = s.substr(len-k, k);
if (pre == suf) {
mid = s.substr(1, len-2);
if (mid.find(pre) < len-1) ans = pre;
}
}
cout << ans << endl;
}

## D-集合问题

#### 输出描述:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int arr[maxn], pos[maxn];

int main(void) {
int n, a, b;
cin >> n >> a >> b;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
sort(arr, arr+n);
bool flag = 0;
for (int i = 0; i < n; i++) {
if (!pos[i]) {
int x = lower_bound(arr, arr+n, a-arr[i]) - arr;
int y = lower_bound(arr, arr+n, b-arr[i]) - arr;
if (!pos[y] && arr[y] + arr[i] == b) {
pos[y] = pos[i] = 1;
continue;
}
if (!pos[x] && arr[x] + arr[i] == a) {
pos[x] = pos[i] = 2;
continue;
}
flag = 1;
break;
}
}
if (flag) puts("NO");
else {
puts("YES");
printf("%d", pos[0]&1);
for (int i = 1; i < n; i++) {
printf(" %d", pos[i]&1);
}
puts("");
}
}

## E-情人节的电灯泡

#### 输出描述:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3+10;
bool arr[maxn][maxn];

int main(void) {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &arr[i][j]);
}
}

while (m--) {
int op;
scanf("%d", &op);
if (op == 1) {
int x, y;
scanf("%d %d", &x, &y);
arr[x][y] = !arr[x][y];
} else {
int x1, y1, x2, y2;
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);

long long ans = 0;
for (int i = x1; i <= x2; i++) {
for (int j = y1; j <= y2; j++) {
if (arr[i][j]) ans++;
}
}
printf("%lld\n", ans);
}
}
return 0;
} 

## F-The Biggest Water Problem

#### 输出描述:

#include <bits/stdc++.h>
using namespace std;

int main(void) {
int n, ans;
cin >> n;
while (n > 10) {
ans = 0;
while (n) {
ans += n % 10;
n /= 10;
}
n = ans;
}
cout << ans << endl;
}

## G-送分啦-QAQ

#### 输出描述:

1)先手不能在第一次把所有的石子取完；
2)之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间（包含1和对手刚取的石子数的2倍）。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4+10;
#define ll long long
ll fib[maxn];

int main(void) {
fib[0] = fib[1] = 1;
for (int i = 2; i < maxn; i++) {
fib[i] = fib[i-1] + fib[i-2];
}

int n;
cin >> n;
for (int i = 2; i < maxn; i++) {
if (fib[i] == n) {
puts("Sha");
return 0;
}
}
puts("Xian");
}

## H-Tree Recovery

#### 题目描述

You have N integers, A1, A2, … , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

#### 输入描述:

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b” means querying the sum of Aa, Aa+1, … , Ab.

#### 输出描述:

You need to answer all Q commands in order. One answer in a line.

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
const int N = 1e5+10;

void pushUp(int rt) {
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void pushDown(int rt, int ln, int rn) {
}
}

void build(int l, int r, int rt) {
if (l == r) {
cin >> sum[rt];
return;
}
int m = (l+r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}

void updata(int L, int R, ll C, int l, int r, int rt) {
if (L <= l && r <= R) {
sum[rt] += C*(r-l+1);
return;
}
int m = (l+r) >> 1;
pushDown(rt, m-l+1, r-m);

if (L <= m) updata(L, R, C, lson);
if (R > m) updata(L, R, C, rson);
pushUp(rt);
return;
}

ll query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return sum[rt];
int m = (l+r) >> 1;
pushDown(rt, m-l+1, r-m);

ll ans = 0;
if (L <= m) ans += query(L, R, lson);
if (R > m) ans += query(L, R, rson);
return ans;
}

int main(void) {
ios::sync_with_stdio(0); cin.tie(0);
int n, m;
while (cin >> n >> m) {
build(1, n, 1);
char ch;
while (m--) {
cin >> ch;
int L, R;
if (ch == 'Q') {
cin >> L >> R;
cout << query(L, R, 1, n, 1) << endl;
} else {
ll C;
cin >> L >> R >> C;
updata(L, R, C, 1, n, 1);
}
}
}
return 0;
}

——EDN