A
简单模拟。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int T,n,a[N];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n); int ans=0,sum=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
if(a[i]==0) ans++,a[i]++;
sum+=a[i];
}
if(sum==0) ans++;
printf("%d\n",ans);
}
}
B
手玩可得 : 将数组 \(a\) 排序后,答案即为 \(a_{n+1}-a_{n}\)。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int T,n,a[N];
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
for(int i=1;i<=2*n;i++) scanf("%lld",&a[i]);
sort(a+1,a+2*n+1);
printf("%lld\n",a[n+1]-a[n]);
}
}
C
题意可转化为 :从原数组中选一个数 \(x\) , 再分别将 \(x\) 与数组中其他数按位去重(即:如果两个数此位均为 1 , 则将此位修改为 0。
显然可以从高至低枚举每一位出现次数是否为 1 ,如是则选 \(x\) 为此数,并将 \(x\) 放至 \(a_1\)。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,a[N],fac[60],vis[60],pos[60];
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
fac[0]=1; for(int i=1;i<=40;i++) fac[i]=fac[i-1]*2;
for(int i=1;i<=n;i++){
for(int j=0;j<=35;j++) if(a[i]&fac[j]) vis[j]++,pos[j]=i;
}
int top=1;
for(int i=35;i>=0;i--) if(vis[i]==1){
top=pos[i];
break;
}
swap(a[1],a[top]);
for(int i=1;i<=n;i++) printf("%lld ",a[i]);
}
D
观察并猜结论得:\(P\) 与 \(T\) 相似,当且仅当 \(P\) 为中心对称图形,判断即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int n,x[N],y[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
if(n&1){ puts("No"); return 0; }
int p1=x[1]+x[n/2+1],p2=y[1]+y[n/2+1],ans=1;
for(int i=1;i<=n/2;i++) if(x[i]+x[n/2+i]!=p1 || y[i]+y[n/2+i]!=p2) { ans=0; break; }
(ans==1)?puts("Yes"):puts("No");
}
E
直接做并不好做,考虑用前缀和转化:
原序列最小字典序等价于:前缀和序列最小字典序。
一段区间 \([l,r]\) 平均数为 :\(\frac{pre_r-pre_{l-1}}{r-(l-1)}\) , 观察这个式子可表示为斜率式。
对区间 \([l,r]\) 进行操作 : \(p_i \rightarrow p_{l-1}+\frac{pre_r-pre_{l-1}}{r-(l-1)}\times (i-l+1)\)。
我们就将其看做点 \((0,pre_0) , (1,pre_1) ,.....(n,pre_n)\),用其维护下凸包即可。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
template <typename T>
inline void read(T &x){
x=0; bool f=0; char ch=getchar();
while(ch<'0' || ch>'9'){ f|=(ch=='-'); ch=getchar(); }
while('0'<=ch && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
if(f) x=-x;
}
int n,top,a[N],pre[N],sta[N];
double slope(int x,int y){
return (double)(pre[y]-pre[x])/(y-x);
}
signed main(){
read(n);
for(int i=1;i<=n;i++) read(a[i]),pre[i]=pre[i-1]+a[i];
for(int i=1;i<=n;i++){
while(top && slope(sta[top-1],i) < slope(sta[top-1],sta[top]) ) top--;
sta[++top]=i;
}
for(int i=1;i<=top;i++){
double ans=slope(sta[i-1],sta[i]);
for(int j=1;j<=sta[i]-sta[i-1];j++) printf("%.10lf\n",ans);
}
}