A. Meeting of Old Friends(Codeforces 714A)
思路
首先我們可以討論兩個區間的位置關係(內含,相交,相等或相離),相離情況下答案爲
比較巧妙的辦法是,令
(以下的代碼用的是直接分類討論的方法)
代碼
#include <bits/stdc++.h>
using namespace std;
long long l1, r1, l2, r2, k, L, R;
int main() {
cin >> l1 >> r1 >> l2 >> r2 >> k;、
// 區間相離
if(r1 < l2 || r2 < l1) {
cout << 0;
}
// 區間相等或區間2包含區間1
else if(l1 >= l2 && r1 <= r2) {
cout << r1 - l1 + (l1 > k || k > r1);
}
// 區間相交
else if(l2 > l1 && r2 < r1) {
cout << r2 - l2 + (l2 > k || k > r2);
}
// 區間相交
else {
L = max(l1, l2);
R = min(r1, r2);
cout << R - L + (L > k || k > R);
}
return 0;
}
B. Filya and Homework(Codeforces 714B)
思路
我們先統計數組中不同數的個數是多少(假設它爲
m=1 或m=2 。此時一定能讓所有的數相等。m=3 。若最大的數減第二大的數等於第二大的數減去最小的數則能夠讓所有數相等,否則不能。m≥4 。此時一定無法讓所有的數相等。
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, m, a[maxn];
int main() {
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
sort(a, a + n);
m = unique(a, a + n) - a;
if(m >= 4) {
puts("NO");
}
else if(m == 1 || m == 2) {
puts("YES");
}
else {
puts(a[2] - a[1] == a[1] - a[0] ? "YES" : "NO");
}
return 0;
}
C.Sonya and Queries(Codeforces 714C)
思路
首先,我們可以將輸入的數字當成
然後,每讀入一個操作符爲
當操作符爲
(賽後發現有更簡單的方法,就是直接將
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxNode = 2e6, sigmaSize = 5;
// Trie的模板
struct Trie {
int ch[maxNode][sigmaSize];
int val[maxNode];
int sz;
Trie() {
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}
int idx(char c) {
return c - '0';
}
void insert(string s, int v) {
int u = 0, n = s.size();
for(int i = 0; i < n; i++) {
int c = idx(s[i]);
if(!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] += v;
}
int find(string s) {
int u = 0, n = s.size();
for(int i = 0; i < n; i++) {
int c = idx(s[i]);
if(!ch[u][c]) {
return 0;
}
u = ch[u][c];
}
return val[u];
}
}o;
int n;
string s, t, opt;
int main() {
ios_base::sync_with_stdio(false);
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> opt >> s;
// 處理成0-1字符串
for(int i = 0; i < s.size(); i++) {
s[i] = (s[i] - '0') % 2 ? '1' : '0';
}
string t;
// 在首部添0
for(int i = 1; i <= 18 - s.size(); i++) {
t.push_back('0');
}
s = t + s;
if(opt != "?") {
o.insert(s, opt == "+" ? 1 : -1);
}
else {
cout << o.find(s) << endl;
}
}
return 0;
}
E. Sonya and Problem Wihtout a Legend(Codeforces 714E)
思路
先來思考一個簡單的問題。當題目中的“嚴格單調遞增”改成“單調非遞減”時,問題該怎樣解決。
用搜索解決肯定是複雜度太高了,如果用動態規劃呢?我們先嚐試劃分階段。假設我們定義階段i爲考慮到第
於是我們定義
現在似乎按照方程遞推就能得解了。但是此處還有兩個問題需要解決。第一,
這樣以來整個問題就解決了。但是原問題似乎還沒得到解決。事實上,我們可以簡單地令所有的
代碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3010;
int n, m, a[maxn], b[maxn];
ll ans, Min[maxn], d[maxn][maxn];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i] = a[i] - i;
b[i] = a[i];
}
// 離散化中的排序
sort(b + 1, b + n + 1);
// 離散化中的去重
m = unique(b + 1, b + n + 1) - b - 1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
d[i][j] = Min[j] + abs(b[j] - a[i]);
}
Min[1] = d[i][1];
// 處理前綴最小值數組
for(int j = 2; j <= m; j++) {
Min[j] = min(d[i][j], Min[j-1]);
}
}
printf("%I64d\n", Min[m]);
return 0;
}
(其它題目略)