Codeforces Round #498 (Div. 3)

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;
}

 

未来可期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值