A.题意:给一数组涂色,有无数种颜色可涂,规定数组的得分为每种颜色的数字的最大值和最小值的差之和,问该数组的最大得分
思路:可以直接将数组排序,然后最大元素和最小元素涂同一种颜色,次大元素和次小元素涂同一颜色,以此类推
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=a,i>=b,i--)
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int a[200200];
void solve() {
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
int ans=0;
for(int i=1;i<=n/2;i++)
{
ans+=a[n+1-i]-a[i];
}
cout<<ans<<endl;
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)solve();
return 0;
}
B.题意:
给定一个数组,每次操作可以将一段连续的区间的数字变成其相反数,问若干次操作后数组元素之和的最大值以及最少的操作次数
思路:
思路:
显然最大值是所有元素绝对值之和
对于最少操作次数,考虑贪心
对于连续负数段,必须进行操作
而遇到不为零的非负数(也就是正数),不在需要操作区间的范围内
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=a,i>=b,i--)
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int a[200200];
void solve() {
int n;
cin>>n;
int sum=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=abs(a[i]);
}
int cnt=0;
bool flag=false;
for(int i=1;i<=n;i++)
{
if(a[i]<0&&!flag)
{
cnt++;
flag=true;
}
if(a[i]>0)
{
flag= false;
}
}
cout<<sum<<" "<<cnt<<endl;
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)solve();
return 0;
}
C.题意:给一颗满二叉树,问从根节点1到达目标位置n的路径的节点总和为?
思路:
从n暴力向1跳即可
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=a,i>=b,i--)
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
void solve() {
int n;
cin>>n;
int ans=0;
while(n)
{
ans+=n;
if(n%2==0)
{
n/=2;
}
else{
n--;
n/=2;
}
}
cout<<ans<<endl;
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)solve();
return 0;
}
D.
题意:给定一颗树,给定q次询问,每次询问给定两个苹果的位置,苹果会沿着当前节点的孩子节点一直到叶子节点,询问苹果可能的下落情况
思路:考虑树形dp
设dp[u]为以u为根节点的字数的叶子节点的数量
通过一遍dfs计算出所有的dp值,然后对于每次询问,根据乘法原理,答案为dp[x]*dpy
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=a,i>=b,i--)
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int dp[200200];
vector <int> mp[200200];
void dfs(int u,int fa)
{
if(mp[u].size()==1)
{
dp[u]=1;
}
for(auto v: mp[u])
{
if(v==fa) {
continue;
}
dfs(v,u);
dp[u]+=dp[v];
}
}
void solve() {
int n,m;
cin>>n;
for(int i=1;i<=n;i++)
{
mp[i].clear();
dp[i]=0;
}
mp[1].push_back(0);
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
mp[u].push_back(v);
mp[v].push_back(u);
}
dfs(1,0);
cin>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
cout<<dp[x]*dp[y]<<endl;
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)solve();
return 0;
}
E.题意:给定m个不同的区间,(区间均为[1,n]子集)q次修改,初始时[1,n]区间所有元素都是0,每次修改可以将指定位置的0改成1(修改操作是有先后次序的),求至少到第几次操作时,才能使得m个区间中至少有1个区间满足:区间内1的数量严格大于0的数量,若无解输出-1
思路:假设第k次操作可行,那么再进行后面的操作也必然可行,故考虑二分答案,check函数中,先计算前缀和,这样在判断m个区间中是否有合法区间时可以做到O(1)查询,check函数复杂度O(n+m)
总的时间复杂度O((n+m)logq)
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=a,i>=b,i--)
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int l[200200];
int r[200200];
int a[200200];
int n,m;
bool check(int mid)
{
vector <int> vis(n+1,0),sum(n+1,0);
for(int i=1;i<=mid;i++)
{
vis[a[i]]=1;
}
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+vis[i];
}
for(int i=1;i<=m;i++)
{
if(sum[r[i]]-sum[l[i]-1]>=(r[i]-l[i]+1)/2+1)return true;
}
return false;
}
void solve() {
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>l[i]>>r[i];
}
int q;
cin>>q;
for(int i=1;i<=q;i++)
{
cin>>a[i];
}
int lf=1ll,ri=q;
while(lf<ri)
{
int mid=(lf+ri)/2;
if(check(mid))ri=mid;
else lf=mid+1;
}
if(check(lf))cout<<lf<<endl;
else cout<<-1<<endl;
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)solve();
return 0;
}