题意:每次选择两个相差绝对值不大于1的数,随机删掉一个。问是否可以通过上述操作,使得数组中只剩下一个元素。
思路:从小到大排个序。判断相邻数之间的差是否有大于1的,有的话则不行。反之则可以。
#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
int main() {
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> v(n);
for (auto& val : v) {
cin >> val;
}
int flag = 1;
sort(v.begin(), v.end());
int i;
for (i = v.size() - 1; i > 0; i--) {
if (v[i] - v[i - 1] > 1) {
flag = 0;
break;
}
}
if (flag)cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
题意:有n个礼物,每个礼物里面有a个糖和b个橘子。可以进行三种不同的操作。
选择一份礼物中的糖,然后吃掉一个。
选择一份礼物中的橘子,然后吃掉一个。
选择一份礼物中的糖和橘子,吃掉一个。
最后要是每份礼物中的糖数量都相等, 橘子数量都相等。但糖和橘子的数量都相等。且数量不能小于等于0。
思路:分别找出糖和橘子的最小数量。因为要是所有的糖数量相等,橘子数量相等,那么只能都变成最小的。然后遍历所有礼物。每个礼物的操作数为max(糖变成最小数量的操作数,橘子变成数量最小的操作数)
#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
bool isPrime(long long x) {
if (x <= 1)return false;
if (x == 2)return true;
if (x % 2 == 0)return false;
long long m = sqrt(x);
for (long long i = 3; i <= m; i += 2) {
if (x % i == 0)return false;
}
return true;
}
long long gcd(long long m, long long n) {
return m % n == 0 ? n : gcd(n, m % n);
}
unordered_map<long long, int> mmid;
long long fib[90];
void initFib() {
fib[0] = fib[1] = 1;
mmid[1] = 1;
int i;
for (i = 2; i < 90; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
mmid[fib[i]] = 1;
}
}
int main() {
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<pii> v(n);
int a_min = INT_MAX;
int b_min = INT_MAX;
for (auto& val : v) {
cin >> val.first;
a_min = min(a_min, val.first);
}
for (auto& val : v) {
cin >> val.second;
b_min = min(b_min, val.second);
}
long long ans = 0;
for (auto& val : v) {
int tmp1 = val.first - a_min;
int tmp2 = val.second - b_min;
ans = ans + max(tmp1, tmp2);
}
cout << ans << endl;
}
return 0;
}
题意:给n个数,问两两组成一个一队,并且所有的队中两数之和要相等。最多可以选择多少队。
思路:暴力。先用map保存每个数出现的次数。然后枚举所有可能是sum。
#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
bool isPrime(long long x) {
if (x <= 1)return false;
if (x == 2)return true;
if (x % 2 == 0)return false;
long long m = sqrt(x);
for (long long i = 3; i <= m; i += 2) {
if (x % i == 0)return false;
}
return true;
}
long long gcd(long long m, long long n) {
return m % n == 0 ? n : gcd(n, m % n);
}
long long fib[90];
void initFib() {
fib[0] = fib[1] = 1;
int i;
for (i = 2; i < 90; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
}
int main() {
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> v(n);
int mmid[110];
memset(mmid, 0, sizeof(mmid));
for (auto& val : v) {
cin >> val;
mmid[val]++;
}
sort(v.begin(), v.end());
int i, j;
int ans = 0;
for (i = 0; i <= 100; i++) {
int cur = 0;
for (j = 1; j <= i / 2; j++) {
cur += min(mmid[j], mmid[i - j]);
}
if (i % 2 == 0)cur += mmid[i / 2] / 2 - mmid[i / 2];
ans = max(ans, cur);
}
cout << ans << endl;
}
return 0;
}
题意:有一个01组成的字符串,要把这个字符串分成若干个子序列,使得每个子序列中没有连续的0或者1。要使的子序列数量最少,并输出每个字符在哪个序列中。
思路:用两个队列保存0和1的下标。当遇到1时,如果0的队列为空,则序列数+1。否则取出队首的一个元素。遇到0的时候正好相反。
#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
bool isPrime(long long x) {
if (x <= 1)return false;
if (x == 2)return true;
if (x % 2 == 0)return false;
long long m = sqrt(x);
for (long long i = 3; i <= m; i += 2) {
if (x % i == 0)return false;
}
return true;
}
long long gcd(long long m, long long n) {
return m % n == 0 ? n : gcd(n, m % n);
}
long long fib[90];
void initFib() {
fib[0] = fib[1] = 1;
int i;
for (i = 2; i < 90; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
}
int main() {
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
string str;
cin >> str;
vector<int> v(n);
int cnt = 0;
int i;
int flag = 0;
v[0] = 1;
deque<int> one,zero;
int ans = 0;
for (i = 0; i < n; i++) {
int tmp;
if (str[i] == '1') {
if (zero.size()) {
tmp = zero.front();
zero.pop_front();
one.push_back(tmp);
}
else {
cnt++;
one.push_back(cnt);
tmp = cnt;
}
}
else {
if (one.size()) {
tmp = one.front();
one.pop_front();
zero.push_back(tmp);
}
else {
cnt++;
zero.push_back(cnt);
tmp = cnt;
}
}
v[i] = tmp;
}
cout << cnt << endl;
for (i = 0; i < n; i++) {
if (i)cout << ' ';
cout << v[i];
}
cout << endl;
}
return 0;
}
题意:有一个n 个顶点的数,顶点为1。每个边都有一个权值。从顶点到叶子节点经过的边的权值和为w。可以进行可以操作 每次将一条边的权值减半(向下取整)。问要使的w<=S。最少要经过几次上诉操作。
思路:w其实就算每个边的权值乘上每个边经过的次数求和求和。所以我们可以先记录一下每条边经过的次数,用堆来维护当前 (权值-权值/2)*经过的次数 最大的边,然后每次修改权重最大的边。
#include
using namespace std;
#define mp(a,b) make_pair(a,b)
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<int, long long> pil;
const long long INF = 1e15;
const int maxn = 2e5 + 10;
bool isPrime(long long x) {
if (x <= 1)return false;
if (x == 2)return true;
if (x % 2 == 0)return false;
long long m = sqrt(x);
for (long long i = 3; i <= m; i += 2) {
if (x % i == 0)return false;
}
return true;
}
long long gcd(long long m, long long n) {
return m % n == 0 ? n : gcd(n, m % n);
}
long long fib[90];
void initFib() {
fib[0] = fib[1] = 1;
int i;
for (i = 2; i < 90; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
}
struct cmp {
bool operator()(const pli& p1, const pli& p2) {
return (p1.first - p1.first / 2) * p1.second < (p2.first - p2.first / 2)* p2.second;
}
};
long long sum = 0;
vector<pil> G[maxn];
priority_queue<pli, vector<pli>, cmp> que;
int dfs(int cur, int fa) {
if (G[cur].size() == 1 && cur != 1) return 1;
int cnt = 0;
for (auto& [a, b] : G[cur]) {
if (a == fa)continue;
int tmp = dfs(a, cur);
cnt += tmp;
que.push(mp(b, tmp));
sum += b * tmp;
}
return cnt;
}
int main() {
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
int i;
long long s;
sum = 0;
int n;
cin >> n >> s;
for (i = 0; i <= n; i++) {
G[i].clear();
}
int a, b, w;
for (i = 0; i < n - 1; i++) {
cin >> a >> b >> w;
G[a].push_back(mp(b, w));
G[b].push_back(mp(a, w));
}
que = {};
dfs(1, 0);
int ans = 0;
while (sum > s) {
ans++;
auto [a, b] = que.top();
que.pop();
sum -= a * b;
a /= 2;
sum += a * b;
que.push(mp(a, b));
}
cout << ans << endl;
}
return 0;
}