A.
思路:先假设一组数122233,总数有6个,中位数为6/2=3,我们如果选择中位数2加1,此时改的这个数2已不再中位数的位置,此数组变为122333,此时中位数还是2未发生改变,因此我们就可以知道,操作数即为改中位数往后与它相同的数的数量,另外还要清楚他那个符号是向上取整,所以7/2 = 3······1 = 4,代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5+10;
int a[N];
void solve()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a+1, a+1+n);
if(n&1) n++; //奇数加一,作用类似于向上取整
int mid = n/2;
int idx = n/2;
int ans = 0;
while(a[idx] == a[mid]&&idx <= n) idx++;
ans = idx - mid;
cout << ans << endl;
memset(a, 0, sizeof a);//一定不要忘了将数组清零啊
}
int main()
{
int t;
cin >> t;
while(t--)
{
solve();
}
return 0;
}
B.
思路:先统计出数组最大的连续子数组和,再通过观察可发现,其数值增加是2的等比数列,因此计算下它的等比数列和即可(可以用快速幂,不过好像也不需要),取模的时候要注意下,代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define int long long
const int N = 2e5+10, mod = 1e9+7;
int a[N];
int qmi(int b, int k, int p)
{
int res = 1;
while(k)
{
if(k&1) res = (long long)res * b%p;
b = (long long)b*b%mod;
k >>= 1;
}
return res;
}
void solve()
{
int n, k; cin >> n >> k;
int sum = 0;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
sum += a[i];
}
sum%=mod;
int maxSum = a[1];
int x = a[1];
for(int i = 2; i <= n; i++)
{
x = (x > 0) ? x + a[i] : a[i];
maxSum = (x > maxSum) ? x : maxSum;
}
if(maxSum < 0) maxSum = 0;
//maxSum一定要先模上mod后再乘,就这个导致了溢出没过
maxSum = maxSum % mod * (qmi(2, k, mod)-1)%mod;
sum = ((sum + mod) % mod + maxSum) % mod;
cout << sum << endl;
memset(a, 0,sizeof a);
}
signed main()
{
int t;
cin >> t;
while(t--)
{
solve();
}
return 0;
}
C.听大佬说这是个比较典的题(但我不会,值得学习)
思路:首先这是个寻找最小的最大值 --> 二分,所以我们可以从1到n进行二分,找到这个x,二分出一个x时,我们可以用dfs进行寻找满足x的长度进行切割,最后统计可以切割出的数量,并与k进行比较,如果大于k,返回true,否则返回false。至于为啥是大于而不是大于等于,因为我统计的是子树的数量,移除k条边产生k+1个子树,所以要大于k,代码如下:
#include <iostream>
#include <vector>
using namespace std;
const int N = 1e5+10;
vector<int> v[N];
int n, m;
int cnt;
//运用贪心,够切了就进行切,产生一子树
int dfs(int u, int p, int t)
{
int num = 1;
for(auto x : v[u])
{
if(x == p) continue;
num += dfs(x, u, t);
}
if(num >= t) //只有节点数量满足条件后,子树数量加1
{
cnt++;
return 0;//把这个子树切掉,对自己的父亲就没有贡献
}
return num;
}
bool check(int x)
{
cnt = 0;
dfs(1, -1, x);
return cnt >= m+1;
}
void solve()
{
cin >> n >> m;
int a, b;
for(int i = 1; i < n; i++)
{
cin >> a >> b;
v[a].push_back(b);
v[b].push_back(a);
}
int l = 1, r = n;
while(l < r)
{
int mid = (l + r + 1) >> 1;
if(check(mid)) l = mid;
else r = mid-1;
}
cout << l << endl;
for(int i = 1; i <= n; i++) v[i].clear();
}
int main()
{
int t;
cin >> t;
while(t--)
{
solve();
}
return 0;
}