Educational Codeforces Round 85 (Rated for Div. 2)

A. Level Statistics

题意:

统计一个游戏的数据情况,p代表目前被玩的次数,d代表被通关的次数,每次玩可以通关或者不通关,或者当前还在玩结果未知。判断给出的记录是否合法。\(1≤n≤100\)

思路:

注意几点:玩的次数不能小于被通关的次数,玩的次数和通过的次数不能随着事件减小,每个时刻玩的次数的人数变化不能小于通关的人数变化。

代码:

#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#include<set>
#include<map>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
int p[100010],c[100010];
int main(){
    int T;
    cin>>T;
    while(T--){
        int n,f=1;
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>p[i]>>c[i];
            if(c[i]>p[i]||p[i]<p[i-1]||c[i]<c[i-1]) f=0;
            if(c[i]-c[i-1]>p[i]-p[i-1]) f=0;
        }
        if(f) cout<<"YES\n";
        else cout<<"NO\n";
    }
    return 0;
}

B. Middle Class

题意:

给出一个每个人的财富值和这个国家对于富人的定义x,现在可以把一些人的财富聚在一起然后平分,求让富人最多可以有多少。\(1≤n≤10^5\)

思路:

先把按财富排序,从大到小每加入一个人计算一下平均值,当平均值小于x时退出遍历,当前被加入的人数就是富人最多的数量

代码:

#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#include<set>
#include<map>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
double a[100010],sum[100010];
int main(){
    int T;
    cin>>T;
    while(T--){
        int n,x;
        cin>>n>>x;
        for(int i=1;i<=n;++i) cin>>a[i];
        sort(a+1,a+1+n,greater<int>());
        for(int i=1;i<=n;++i){
            sum[i]=sum[i-1]+a[i];
        }
        int ans=0;
        for(int i=1;i<=n;++i){
            if(sum[i]/(i*1.0)>=x) ans=i;
        }
        cout<<ans<<endl;
    }
    return 0;
}

C. Circle of Monsters

题意:

有n个怪兽站成一个环,每个怪物的血量不同,你可以向每个怪物打一枪子弹造成1的伤害,当一个怪物的血量变成0时会死并对它的下一个怪物造成一个爆炸伤害(每个怪物的爆炸伤害也不同),求最少开多少枪可以消灭所有怪物。\(2≤n≤300000\)

思路:

首先我们可以确定一下每个怪物最少要被打多少枪,即它的血量减去它上一个怪物的爆炸伤害(小于0时表示最少可以打0枪),当对每个怪物都造成至少的伤害,那么再把任意一个怪物打死,那么所有的怪物都会被连续炸死,所以把剩余血量最少的怪物打死。

代码:

#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
LL a[300010],b[300010 ];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;++i) scanf("%lld%lld",&a[i],&b[i]);
        LL res=0;
        for(int i=0;i<n;++i) {
            LL t=b[(i-1+n)%n];
            if(a[i]>t) res+=a[i]-t,a[i]=t;
        }
        LL mn=1e15;
        for(int i=0;i<n;++i){
            if(mn>a[i]) mn=a[i];
        }
        res+=mn;
        printf("%lld\n",res);
    }
    return 0;
}

D. Minimum Euler Cycle

题意:

给出一个n个点的图形,n个点之间都互相有两条方向相反的边,求按走的点编号字典序最小的顺序把所有边走一遍(不能走重边),求序列的l~r区间的走法。\(2≤n≤10^5,r−l+1≤10^5\)

思路:

举个例子,当n=5时:完整的遍历的序列是:12131415 232425 3435 45 1。这个规律就很显然了,把没用序列一个个直接跳过,有用的区间滚一遍,时间复杂度是可以接受的。

代码:

#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#include<set>
#include<map>
using namespace std;
const int N=100010;
int a[N];
long long n,l,r,cnt;
void solve(int f){
    for(int i=f+1;i<=n;++i){
        cnt++;
        if(cnt>=l&&cnt<=r) cout<<f<<" ";
        cnt++;
        if(cnt>=l&&cnt<=r) cout<<i<<" ";
    }
}
int main(){
    int T;
    cin>>T;
    while(T--){
        cin>>n>>l>>r;
        cnt=0;
        long long f=1;
        while(f<n){
           if(cnt+(n-f)*2>=l&&cnt<=r)
                solve(f);
           else
                cnt+=(n-f)*2;
           f++;
        }
        if(++cnt<=r) cout<<1<<" ";
        cout<<endl;
    }
    return 0;
}
posted @ 2020-04-12 13:44  0x4f  阅读(128)  评论(0编辑  收藏  举报