cf1311

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)的和。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值