A. Add Odd or Subtract Even
签到题
答案只能是0,1,2
#include<cstdio>
#include<iostream>
using namespace std;
int t;
long long a;
long long b;
int main(){
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&a,&b);
if(a==b){
printf("0\n");
}else{
if(a>b){
if((a-b)%2==1){
printf("2\n");
}else{
printf("1\n");
}
}else{
if((b-a)%2==0){
printf("2\n");
}else{
printf("1\n");
}
}
}
}
return 0;
}
B. WeirdSort
可交换的连续区间,对区间进行排序,对原数组进行排序,对比
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int g[102];
int a[102];
int p[102];
int s[102];
int t;
int n,m;
bool flag;
int main(){
scanf("%d",&t);
while(t--){
memset(g,0,sizeof(g));
flag=false;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[i]=a[i];
g[i]=i;
}
for(int i=1;i<=m;i++){
scanf("%d",&p[i]);
}
sort(s+1,s+n+1);
sort(p+1,p+1+m);
for(int i=m;i>=1;i--){
g[p[i]]=max(g[p[i]+1],p[i]+1);
}
for(int i=1;i<=n;){
sort(a+i,a+1+g[i]);
i=g[i]+1;
}
for(int i=1;i<=n;i++){
if(a[i]!=s[i]){
flag=true;
break;
}
}
if(flag)printf("No\n");
else printf("Yes\n");
}
return 0;
}
C. Perform the Combo
p的顺序与最终结果没有影响,所以可以先记录一下失误的位置,最后扫一遍加起来
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long a[27];
int vis[200005];
char str[200005];
long long ans[27];
int t,n,m;
int main(){
scanf("%d",&t);
while(t--){
memset(a,0,sizeof(a));
memset(ans,0,sizeof(ans));
memset(vis,0,sizeof(vis));
scanf("%d%d\n",&n,&m);
for(int i=1;i<=n;i++){
scanf("%c",&str[i]);
ans[str[i]-'a'+1]++;
}
for(int j=1;j<=m;j++){
int l;
scanf("%d",&l);
vis[l]++;
}
for(int i=1;i<=n;i++){
a[str[i]-'a'+1]++;
for(int j=1;j<=26;j++){
ans[j]+=vis[i]*a[j];
}
}
for(int i=1;i<=26;i++)printf("%lld ",ans[i]);
printf("\n");
}
return 0;
}
D. Three Integers
枚举
注意范围:1<=A<=2a;根据A找相应的B和C
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int A,B,C;
int t;
int jdz(int u){
if(u<0)return -u;
else return u;
}
int main(){
scanf("%d",&t);
while(t--){
int ans=0x7fffffff;
int AA;
int AB;
int AC;
scanf("%d%d%d",&A,&B,&C);
for(int a=1;a<=(2*A);a++){
for(int b=a;b<=(2*B);b+=a){
if(ans>(jdz(((C/b)*b)-C)+jdz(A-a)+jdz(B-b))){
ans=jdz(((C/b)*b)-C)+jdz(A-a)+jdz(B-b);
AA=a;
AB=b;
AC=(C/b)*b;
}
if(ans>(jdz(((C/b)*b)-C+b)+jdz(A-a)+jdz(B-b))){
ans=jdz(((C/b)*b)-C+b)+jdz(A-a)+jdz(B-b);
AA=a;
AB=b;
AC=(C/b)*b+b;
}
}
}
printf("%d\n",ans);
printf("%d %d %d\n",AA,AB,AC);
}
return 0;
}
E. Construct the Binary Tree
可以预先算出深度和的最小值和最大值,分别对应最偏满的二叉树和一条链。在最大值和最小值之间的都可以,因为在链的情况下可以一个一个地把叶子向上移,并最终可以成为类似满树的状态。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int fa[5003];
int cnt[5003];
int dep[5003];
int pow[21];
int ava[5003];
int dest;
int sest;
int t;
int n;
int sumd;
int main(){
scanf("%d",&t);
pow[0]=1;
for(int i=1;i<=20;i++){
pow[i]=pow[i-1]*2;
}
while(t--){
memset(fa,0,sizeof(fa));
memset(cnt,0,sizeof(cnt));
memset(dep,0,sizeof(dep));
memset(ava,0,sizeof(ava));
scanf("%d%d",&n,&sumd);
dest=n*(n-1)/2;
sest=0;
int h=1;
while(n>=((1<<h)-1)){
h++;
}
h--;
for(int i=0;i<h;i++){
sest+=i*pow[i];
}
sest+=(n-(1<<h)+1)*h;
if(sumd<sest||sumd>dest){
printf("NO\n");
continue;
}
//cout<<dest<<" "<<sest;
for(int i=2;i<=n;i++){
fa[i]=i-1;
cnt[i-1]=1;
dep[i]=i-1;
}
int cur=dest;
ava[1]=1;
while(cur>sumd){
int u;
for(int i=1;i<=n;i++){
if(!ava[i]&&cnt[i]==0){
u=i;
break;
}
}
int ifAva=1;
for(int j=1;j<=n;j++){
if(dep[j]==dep[u]-2&&cnt[j]<2){
cnt[fa[u]]--;
fa[u]=j;
cnt[j]++;
ifAva=0;
dep[u]--;
cur--;
break;
}
}
if(ifAva)ava[u]=1;
}
printf("Yes\n");
for(int i=2;i<=n;i++){
printf("%d ",fa[i]);
}
printf("\n");
}
return 0;
}
F. Moving Points
离散化+树状数组
xi<xj且vi>vj的情况下贡献为零,找到剩余的区间距离和。
对v进行离散化,再按x进行排序,再维护一个cnt(符合条件的点出现的次数)和sum(符合条件的点坐标和),答案加上xi*cnt[v[i]]-sum[v[i]]。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
long long ans;
struct node{
long long x;
long long v;
}P[200005];
long long v[200005];
long long cnt[200005];
long long sum[200005];
bool cmp1(node &a,node &b){
return a.x<b.x;
}
bool cmp2(node &a,node &b){
return a.v<b.v;
}
int n;
int t;
int lowbit(int u){
return u&(-u);
}
void upd_cnt(int i,int k){
while(i<=n){
cnt[i]+=k;
i+=lowbit(i);
}
}
void upd_sum(int i,int k){
while(i<=n){
sum[i]+=k;
i+=lowbit(i);
}
}
long long get_sum(int i){
long long res=0;
while(i>0){
res+=sum[i];
i-=lowbit(i);
}
return res;
}
long long get_cnt(int i){
long long res=0;
while(i>0){
res+=cnt[i];
i-=lowbit(i);
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&P[i].x);
}
for(int i=1;i<=n;i++){
scanf("%lld",&P[i].v);
}
sort(P+1,P+1+n,cmp2);
v[1]=1;
for(int i=2;i<=n;i++){
if(P[i].v==P[i-1].v){
v[i]=v[i-1];
}else{
v[i]=v[i-1]+1;
}
}
for(int i=1;i<=n;i++){
P[i].v=v[i];
}
sort(P+1,P+1+n,cmp1);
for(int i=1;i<=n;i++){
ans+=(get_cnt(P[i].v)*P[i].x-get_sum(P[i].v));
upd_cnt(P[i].v,1);
upd_sum(P[i].v,P[i].x);
}
printf("%lld\n",ans);
return 0;
}
其实还有一种不用树状数组的方法,有一种n求所有(xi -xj)的和。