A. Eshag Loves Big Arrays
题意
对于数列A,任选子串,删除大于平均值的数,请问最多可以删除多少个元素
分析
- 对于任意大于最小值的元素总可以被删除,所以只需统计最小的元素出现了几次即可
参考程序
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
using namespace std;
const int maxn=200010;
int t,n,m,num[maxn];
int main(){
scanf("%d",&t);
while(t--){
int ans=0,minn=(1<<30);
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);
if(x<minn){
minn=x,ans=1;
}else if(x==minn){
ans++;
}
}
printf("%d\n",n-ans);
}
}
B. Sifid and Strange Subsequences
题意
对于数列A,挑选出子串,使得不等式对于任意元素均成立
分析
- 从小到大排序,显然如果一个数不能被选,那么他之后(大于他)的数也不能被选,所以从小往大扫,贪心选即可
参考程序
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
using namespace std;
const int maxn=200010;
int t,n,m,num[maxn];
int main(){
scanf("%d",&t);
// t=1;
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
sort(num+1,num+1+n);
int dt=(1<<30);
for(int i=2;i<=n;i++){
dt=min(dt,num[i]-num[i-1]);
if(dt<num[i]){
printf("%d\n",i-1);
goto ed;
}
}
printf("%d\n",n);
ed:;
}
}
C. Parsa's Humongous Tree
题意
给定树T,每个节点都有两个属性和,每个可以在和之间选择一个数,每条边的权值为所链两点数的差的绝对值,整棵树的总价值为全部边的权值之和,求整棵树的最大总价值
分析
- 对于任意节点,选择边界值总能获得更高的价值
- 所以在每个节点设置表示这个节点选择能得到的总价值,和表示这个节点选择能得到的总价值
- 更新所有子树可以得到答案
参考程序
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
using namespace std;
const int maxn=1e5+10;
int t,n;
long long f[maxn],g[maxn],l[maxn],r[maxn];
vector<int> E[maxn];
void dfs(int u,int fa){
if(E[u].size()==1 && u!=1){
f[u]=g[u]=0;
return ;
}
for(int i=0,z=E[u].size();i<z;i++){
int v=E[u][i];
if(v==fa) continue;
dfs(v,u);
f[u]+=max(f[v]+abs(l[v]-l[u]),g[v]+abs(r[v]-l[u]));
g[u]+=max(f[v]+abs(l[v]-r[u]),g[v]+abs(r[v]-r[u]));
}
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
}
dfs(1,1);
printf("%lld\n",max(f[1],g[1]));
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(int i=1;i<=n;i++) E[i].clear();
}
}
D. Kavi on Pairing Duty
题意
对于2n个节点,可以选择不重复的n对节点连接,使得每两个节点,要不然完全包含,要不然长度相等,求方案数
分析
- 对于任意长度n,合法的方案包含以下情况
- 长度n-1的所有合法情况最外面加一层,长度n-2的所有合法情况最外面加两层等等
- 相邻点直接相连
- 长度n的线段,两两配对
- 对于,长度为2y内部以长度为y的线段两两配对
参考程序
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<string>
using namespace std;
const int mo=998244353;
const int maxn=1e6+10;
int n;
long long ans[maxn],pre[maxn];
int prime[maxn],cnt=0;
int main(){
scanf("%d",&n);
if(n==1) return !printf("1");
if(n==2) return !printf("3");
for(int i=2;i<n;i++) for(int j=i;j<=n;j+=i) prime[j]++;
ans[0]=1,ans[1]=1,ans[2]=3;
pre[0]=1,pre[1]=2,pre[2]=5;
for(register int i=3;i<=n+1;i++){
ans[i]+=prime[i];
ans[i]=(ans[i]+pre[i-1])%mo;
pre[i]=(pre[i-1]+ans[i])%mo;
}
printf("%lld",ans[n]+1);
}