首页 > 技术文章 > Codeforces Round #519 by Botan Investments(A,B,C,D,E)

zookkk 2018-10-29 20:29 原文

A:水题。题目大意就是找到最小的k使得n*k-sum>sum

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e2+9;
int a[maxn];
int main(){
	int i,j,k,n;
	cin>>n;
	int mi=-1;
	int sum=0;
	for(i=0;i<n;i++){
		cin>>a[i];
		sum+=a[i];
		if(a[i]>mi)mi=a[i];
	}
	if(n*mi-sum>sum){
		cout<<mi<<endl;
		return 0;
	}
	while(n*mi-sum<=sum){
		mi++;
	}
	cout<<mi<<endl;
}

B题:暴力枚举。题目大意给你一串a序列,要求你找出不同长度的x序列

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e5+9;
int a[maxn],p[maxn];
int main(){
	int i,j,k,n;
	cin>>n;
	for(i=1;i<=n;i++){
		cin>>a[i];
	}
	a[0]=0;
	for(i=1;i<=n;i++){
		p[i]=a[i]-a[i-1];
	}
	int ans[maxn],num=0;
	for(i=1;i<=n;i++){
		int u=i,flag=0;;
		for(j=1;j<=n-u;j++){
			if(p[i+j]==p[j])continue;
			else flag=1;
		}
		if(flag==0){
			ans[num++]=u;
		}
	}
	cout<<num<<endl;
	for(i=0;i<num;i++){
		if(i!=num-1)
		cout<<ans[i]<<' ';
		else cout<<ans[i]<<endl;
	}
}

其实就是另开一个数组p来储存a[i]-a[i-1]的值,然后就是找了个序列合法的周期的个数。刚开始想的时候想复杂了,wa了一发,其实就是枚举周期长度,暴力查找看这个周期合不合法就行了。

C题:比赛中没做出来。。。。可恶啊,还是太菜了,后来仔细一想,其实这题有点类似与山脉吧,在山顶和山底选择翻转。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e5+9;
int ans[maxn];
int main(){
	int i;
	string s;
	cin>>s;
	int len=s.size();
	int flag=0;
	for(i=1;i<len;i++){
		if(s[i]<s[i-1]){
			ans[i-1]=1;
			if(s[i+1]==s[i]){
				flag=1;
			}
			else if(s[i+1]!=s[i]){
				ans[i]=1;
			}
		}
		if((s[i+1]>s[i]&&flag)||(i==len-1&&flag)){
			ans[i]=1;
			flag=0;
		}	
	}
	for(i=0;i<len;i++){
		if(i!=len-1){
			cout<<ans[i]<<' ';
		}
		else cout<<ans[i]<<endl;
	}
}

D题:这道题其实可以转换为求有多少个最长公共字段。我们可以开一个二维数组pre[i][j]用于储存每一个字符串每一个数的前面一个数,然后依次进行比对就行了

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e5+9;
int a[11][maxn],pre[11][maxn],cnt[maxn];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,k,n,m;
    cin>>n>>m;
    for(i=1;i<=m;i++){
        for(j=1;j<=n;j++){
            cin>>a[i][j];
            pre[i][a[i][j]]=a[i][j-1];
        }
    }
    long long ans=n,flag=0;
    for(i=2;i<=n;i++){
        int tmp=a[1][i];
        flag=0;
        for(j=1;j<=m;j++){
            if(pre[j][tmp]!=pre[m][tmp]){
                flag=1;
                break;
            }
        }
        if(!flag){
            cnt[i]=cnt[i-1]+1;
        }
        ans+=cnt[i];
    }
    cout<<ans<<endl;
}

E题:这道题再次让我意识到我的读题能力是多么的糟糕,FA♂Q。本来还想是什么二分图匹配的。。。搞鬼鬼,又看错题。题目给出了每个人分别做第一题的得分和第二题的得分,1个人可以与多个人组队,不过每次组队要求队伍的得分最少,特别的,有m对人不愿意组队,题目要求按顺序输出每个人的总得分。我让第一个人第一题得分为x1,第二题得分为y1,第二个人第一题得分为x2,第二题得分为y2,此时有两种配对方式,(x1,y2),(x2,y1),若选择第一种配对方式则必须满足x1+y2<=x2+y1,移项得x1-y1<=x2-y2。我们以x-y的值对每个人进行排序,通过前缀和来计算其全部的和,再减去不能组队的人的值就是所求的答案。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=3e5+9;
struct node{
    long long x,y,id,sub,val;
}a[maxn];
bool cmp(node a,node b){
    return a.sub<b.sub;
}
long long pre[maxn],suf[maxn],res[maxn];
vector<long long>Sub[maxn];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,n,m;
    cin>>n>>m;
    for(i=1;i<=n;i++){
        cin>>a[i].x>>a[i].y;
        a[i].id=i;
        a[i].sub=a[i].x-a[i].y;
    }
    for(i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        long long val=min(a[u].x+a[v].y,a[u].y+a[v].x);
        Sub[u].push_back(val);
        Sub[v].push_back(val);
    }
    sort(a+1,a+n+1,cmp);
    for(i=1;i<=n;i++){
        pre[i]=pre[i-1]+a[i].y;
        suf[i]=suf[i-1]+a[i].x;
    }
    for(i=n;i>=1;i--){
    //  suf[i]=suf[i+1]+a[i].x;
    }
    for(i=1;i<=n;i++){
        int id=a[i].id;
        res[id]=pre[n]-pre[i]+a[i].x*(n-i)+suf[i-1]+a[i].y*(i-1);
        int len=Sub[id].size();
        for(j=0;j<len;j++){
            res[id]-=Sub[id][j];
        }
    }
    for(i=1;i<=n;i++){
        if(i!=n)
        cout<<res[i]<<' ';
        else{
            cout<<res[i]<<endl;
        }
    }
}

 

推荐阅读