A
https://codeforces.com/contest/1006/problem/A
思路:
每次操作等于(x - 1) ^ 1 + 1,发现奇数会+1然后再-1,偶数却只能-1。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
for(int i = 0; i < n; i++)
if(p[i] & 1)
continue;
else
p[i]--;
for(int i = 0; i < n; i++){
if(i)
cout << " ";
cout << p[i];
}
cout << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
B
https://codeforces.com/contest/1006/problem/B
思路:
题意可理解为求最大的k个数之和,难点在于要记录每次分割的方式。
可以采用增加一个数组来作副本,在里面找sort过的数组中的前k个数的位置。
最后可能结果不够长,可以把最后一段延长到末尾。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p, c;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> k;
p.resize(n);
c.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
for(int i = 0; i < n; i++)
c[i] = p[i];
sort(p.begin(), p.end());
int res = 0;
for(int i = n - 1, j = 0; j < k; j++, i--)
res += p[i];
cout << res << endl;
vi q;
for(int i = 0, j = 1; i < n; i++, j++){
bool found = false;
for(int t = n - k; t < n; t++){
if(c[i] == p[t]){
p[t] = -1;
found = true;
break;
}
}
if(found){
q.push_back(j);
j = 0;
}
}
int sum = 0;
for(int i = 0; i < (int)q.size(); i++)
sum += q[i];
if(sum < n)
q[q.size() - 1] += n - sum;
for(int i = 0; i < (int)q.size(); i++){
if(i)
cout << " ";
cout << q[i];
}
cout << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
C
https://codeforces.com/contest/1006/problem/C
思路:
放左右两个指针,分别向对方移动,左指针在(左 <= 右)情况下右移,右指针则相反。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vll p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
ll res = 0;
ll u = 0, v = 0;
for(int i = 0, j = n - 1; i <= j; ){
if(u < v)
u += p[i++];
else if(u > v)
v += p[j--];
if(u == v){
res = max(res, u);
u += p[i++];
}
}
cout << res << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
D
https://codeforces.com/contest/1006/problem/D
思路:
分四种情况讨论。
如果a[i] == b[i],直接忽略不做任何操作。
如果a[i] != b[i],a[i] == a[n - i + 1] && b[i] == b[n - i + 1],先交换a[i],b[i],再交换a[i],a[n - i + 1];
如果a[i] != b[i],a[i] == b[n - i + 1] || a[n - i + 1] == b[i],交换a[i], a[n - i + 1];
如果a[i] != b[i],b[i] == b[n - i + 1],交换a[i],b[i],再交换b[i], b[n - i + 1];
最后再扫一遍统计要修改的次数。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi pass;
string str, ptr;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
cin >> str >> ptr;
for(int u = 0, v = n - 1; u < v; u++, v--){
if(str[u] != ptr[u]){
if(str[v] == ptr[v])
continue;
if((str[u] == str[v] && ptr[u] == ptr[v])){
swap(str[u], ptr[u]);
swap(str[u], str[v]);
}
else if(str[u] == ptr[v] || str[v] == ptr[u])
swap(str[u], str[v]);
else if(ptr[u] == ptr[v])
swap(str[u], ptr[v]);
}
}
int res = 0;
for(int i = 0; i < n; i++)
if(str[i] != ptr[i])
res++;
cout << res << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
E
https://codeforces.com/contest/1006/problem/E
思路:
直接来个类似于排序二叉树的先序遍历,记录每个点的儿子总数和每个点出现在遍历序列的位置。
每次询问,先判断其儿子总数是否不小于k,再得到它的位置 +(k - 1) 上的值, 就是所求。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi seq, siz, pos;
vii g;
int cnt_sub(int u){
siz[u] = 1;
seq.push_back(u);
pos[u] = seq.size() - 1;
for(int i = 0; i < (int)g[u].size(); i++){
int v = g[u][i];
if(siz[v])
continue;
siz[u] += cnt_sub(v);
}
return siz[u];
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m;
g.resize(n, vi(0));
for(int i = 1; i < n; i++){
int u;
cin >> u;
u--;
g[u].push_back(i);
}
pos.resize(n);
siz.resize(n);
cnt_sub(0);
while(m--){
int u, v;
cin >> u >> v;
u--;
if(siz[u] >= v)
cout << seq[pos[u] + v - 1] + 1 << endl;
else
cout << -1 << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
F
https://codeforces.com/contest/1006/problem/F
思路:
利用meet in the middle的思想降低暴力的复杂度。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m;
ll k;
vector< vector< map<ll, int> > > dp;
vector<vll> mat;
void top_to_bottom(int r, int c, int cnt, int limit, ll cur){
if(r > n || c > m)
return;
if(cnt == limit){
dp[r][c][cur]++;
return;
}
top_to_bottom(r + 1, c, cnt + 1, limit, cur ^ mat[r + 1][c]);
top_to_bottom(r, c + 1, cnt + 1, limit, cur ^ mat[r][c + 1]);
}
ll bottom_to_top(int r, int c, int cnt, int limit, ll cur){
if(r < 1 || c < 1)
return 0;
if(cnt == limit)
return dp[r][c][cur ^ k];
return bottom_to_top(r - 1, c, cnt + 1, limit, cur ^ mat[r][c]) + bottom_to_top(r, c - 1, cnt + 1, limit, cur ^ mat[r][c]);
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m >> k;
mat.resize(n + 2, vll(m + 2));
dp.resize(n + 2, vector< map<ll, int> >(m + 2));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> mat[i][j];
int mid = (n + m - 2) >> 1;
top_to_bottom(1, 1, 0, mid, mat[1][1]);
cout << bottom_to_top(n, m, 0, n + m - 2 - mid, 0) << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
未来可期。