【浮*光】【Codeforces Round #481 (Div. 3)】 解题报告hhhh ——来自蒟蒻的第一次cf留念

15 篇文章 0 订阅

参加的模拟赛,所以不太真实w

为了洛谷五月月赛(0519晚上)准备ing

【Codeforces Round #481 (Div. 3)】低级比赛...

考试规定时间里写了五题(虽然借助了一下电脑的功能qaq)因为是蒟蒻所以要...认真学习

A题,题目链接:http://codeforces.com/contest/978/problem/A


#include <bits/stdc++.h>
using namespace std;
/*【删除重复】 
Petya有一个由n组成的数组。他想删除重复的元素。
希望对数组的每个元素只保留最右边出现的。其余唯一元素的相对顺序不应更改。*/
int a[51],b[51];
bool markk[1009];
int main(){
    int n,len=0; scanf("%d",&n);
    memset(markk,false,sizeof(markk));
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=n;i>=1;i--)
        if(!markk[a[i]]){
            b[++len]=a[i]; markk[a[i]]=true;
        }
    printf("%d\n",len);
    for(int i=len;i>=1;i--)
        printf("%d ",b[i]);
    return 0;
}


B题,题目链接http://codeforces.com/contest/978/problem/B

#include <bits/stdc++.h>
using namespace std;
/*【xxx的删除】 不能有连续三个x,求删去最小个数 */
string s;
int main(){
    int n,len=0,ans=0; scanf("%d",&n);
    cin>>s;
    for(int i=0;i<n;i++){
        if(s[i]=='x'&&len>=2) ans++;
        else
            if(s[i]!='x') len=0;
            else len++;
    }
    printf("%d\n",ans);
    return 0;
}


C题,题目链接http://codeforces.com/contest/978/problem/C

(这个题没写出来qaq 因为二分写错了...现在还不知道该怎么改...)


/* 寻找总订单号对应的位置。
输出m行。宿舍号码f,这个宿舍的房间号码k。 */
/*【思路】使每封信都有一个前缀编号,这个前缀编号是它前面的一个房间的编号,复杂度:O(nlogn) */

#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,e) for(int i=s;i<=e;i++)
const int MAXN = 2e5+10;
typedef long long LL;
LL d[MAXN],r[MAXN],sum[MAXN];
int main(){
    int n,m; cin>>n>>m;
    d[0] = 0; sum[0] = 0;
    rep(i,1,n){ cin>>d[i]; d[i]=d[i]+d[i-1]; }
    rep(i,0,m-1) cin>>r[i];
    rep(i,0,m-1){//找当前room的前缀,所以-1
        int pos=lower_bound(d,d+n+1,r[i])-d-1; sum[i]=pos;
    }
    rep(i,0,m-1){
        cout<<sum[i]+1<<" "<<r[i]-d[sum[i]]<<endl;
    }
    return 0;
} 


D题,题目链接http://codeforces.com/contest/978/problem/D


#include <bits/stdc++.h>
using namespace std;
/*(题意不好理解的一个题)--我们老大就是没看懂题...
给你一个数列,你可以操作一次将一个数+1,-1或者不变(只能变一次@-@),
现在要让这个数列变成等差数列,问最少需要操作多少次,如果不能变成等差数列直接输出-1。
枚举第一个数+0、-1、+1作为首项,枚举公差+1、-1、+2、-2,判断是否符合条件。 */
const int maxn = 1e5 + 10;
int a[maxn];
int main(){
    int n,ans=1e9;
    cin>>n;
    for(int i = 0; i < n; i++) cin>>a[i];
    for(int i = -1; i <= 1; i++){//枚举a[0]的变化
        for(int j = -1; j <= 1; j++){//枚举a[1]的变化
            int d = (a[1]+j) - (a[0]+i);//此时等差数列的公差
            int cnt = abs(i);
            //cnt为改变的个数,首先判断a[0]是否改变,a[0]改变,i为+1或-1
            int k;//a[k]与以a[0]为起点的相差k个公差
            for(k=1;k<n;k++){
                int x = abs(a[k]-(a[0]+i+k*d));
                if(x>1) break;//差x比1大,即三种改变方案等差数列均不成立
                cnt+=x;//如果x为1,说明这个数需要改变,所以cnt要加
            }
            if(k==n) ans=min(ans,cnt);//寻找最小
        }
    }
    cout << (ans < 1e9 ? ans : -1);//判断是否有解
    return 0;
}


E题,题目链接http://codeforces.com/contest/978/problem/E

#include <bits/stdc++.h>
using namespace std;

/* 题意:x是此站当前人数,y是离开时公共汽车上的乘客数量,系统记录y−x。
   如果公共汽车的容量等于w,那么第一个公共汽车可以有多少人可以乘坐?
   求方案数(减时>0;加时<w的取值范围);如果情况是矛盾的(即对于任何最初的乘客数量会有矛盾),打印0。 
【分析】设a[i]=y[i]-x[i]……①  x[i+1]=y[i],将①从1到n项累加可得Σa[i]=y[n]-x[1]……②
 通过②式来求每一站的最多可以站多少人,最少可以站多少人x[1]=y[n]-Σa[i],y[n]∈[0,w]
 每一站取交集,{要考略到这个集合不存在}的情况  */

int main(){
    int n,w; scanf("%d%d",&n,&w);
    int maxn=-99999999,minn=0,sum=0,aa=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&aa); sum+=aa; 
        if(sum>w||sum<-w){ cout<<0<<endl; return 0; }
        maxn=max(sum,maxn); minn=min(sum,minn); 
    }
    if(maxn<0) printf("%d\n",minn+w+1); //判断成立时有一些坑...
    else if(minn<0){
        if(w-maxn+minn>=0) printf("%d\n",w-maxn+minn+1);
        else printf("0\n");
        }
    else printf("%d\n",w-maxn+1);
    return 0;
}

F题,题目链接http://codeforces.com/contest/978/problem/F

#include <bits/stdc++.h>
using namespace std;

/* 题意:程序员a的技能严格大于程序员b (ra>rb)时,可以成为程序员b的导师。 
        一些人会吵架,不能有师徒关系
分析》创建一个struct node,包含skill值和id(序号),
然后对skill值进行排序,从前往后搜索,计算出每一个id收徒弟的数目,
然后在将输入的k对吵架的减去,注意这里减是有条件的,
skill大的那一方的徒弟数减一,而skill小的那一方不用 */

const int maxn =1e6+10;
int idx[maxn],res[maxn];
struct node{
    int x,id;//技能和编号
    node(int x=0,int id=0):x(x),id(id) {} //便于存入
    bool operator <(const node &q)const {
        return x==q.x?id<q.id:x<q.x;//重载小于号
    }//优先x排序,再排id
}q[maxn];
int main(){
    int n,k; while(cin>>n>>k) {
        for(int i=0; i<n; i++) {
            int x; cin>>x;//x就是技能值
            q[i+1]=node(x,i+1);
        }//注意编号的起始0、1关系
        sort(q+1,q+n+1);
        for(int i=0; i<n; i++) idx[q[i+1].id]=i+1;//idx[原]=排序后i+1//重新编号
        res[q[1].id]=0;//最小的,肯定没有徒弟
        for(int i=2; i<=n; i++){
            if(q[i].x>q[i-1].x) res[q[i].id]=i-1;//徒弟个数
            else res[q[i].id]=res[q[i-1].id];
        }
        while(k--){//判断仇人
            int u,v; cin>>u>>v;
            u=idx[u]; v=idx[v];
            if(q[u].x>q[v].x) res[q[u].id]--;//较大的减去一个人
            if(q[v].x>q[u].x) res[q[v].id]--;
        }
        for(int i=1; i<=n; i++) {
            cout<<res[i]<<" ";
        }
        cout<<endl;
    }
}

G题,题目链接http://codeforces.com/contest/978/problem/G

(这题题意都不太理解qaq 太蠢辣 所以拿了神犇的代码qwq)


/* 期末复习周持续n天,有m场考试,每场考试有如下信息:
①si表示知道第i门课的考试时间是在第si天的时候
②di表示第i门课的考试时间
③ci表示准备第i门课需要ci天的复习,在考试的那一天不能复习
问n天中每一天都需要干什么?
休息(输出0),复习(输出复习那一门科目的id),考试(输出m+1)
思路:按照di排序(即按照截止时间),然后反过来暴力扫一遍
对于s(i)大的我们进行优先复习,所以优先队列维护一下si即可 */

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
using namespace std;

 /* //第一种代码,讲的很靠谱但是...嗯...结果很神奇
#define LL long long
#define ALL(a) a.begin(), a.end()
#define mk make_pair
#define fi first
#define se second
const int maxn = 1e3 + 5;
vector<int> day[maxn];
int n,m;
int d[maxn],s[maxn],c[maxn];
int ans[maxn];

bool solve(){
    memset(ans, -1, sizeof(ans));
    for (int i = 1; i <= m; i++){
        day[d[i]].push_back(i);
        ans[d[i]]=m+1;
    }
    priority_queue<pair<int, pair<int, int> > > que;
    for(int i=n;i>=1;i--){
        if(day[i].size()>0)
            for (int j=0;j<day[i].size();j++){
                int p=day[i][j];
                que.push(mk(s[p],mk(c[p],p)));
            }
        if(ans[i]!=-1) continue;
        if(que.empty()){//休息
            ans[i]=0; continue;
        }
        int spos = que.top().fi;
        int restday = que.top().se.fi;
        int pos = que.top().se.se;
        que.pop();
        if (spos > i && restday > 0) return false;
        restday--;
        ans[i] = pos;
        if (restday == 0){
            continue;
        }
        que.push(mk(spos, mk(restday, pos)));
    }
    if (!que.empty()) return false;
    for (int i = 1; i <= n; i++){
        printf("%d ", ans[i]);
    }
    cout << endl;
    return true;
}

int main(){
    cin>>n>>m;
    for(int i = 1; i <= m; i++)
        scanf("%d%d%d",&s[i],&d[i],&c[i]);
    if (solve() == false) puts("-1");
    return 0;
}*/ 

/* //第二种代码:能ac的那种,先膜拜一下qaq
const int inf=0x3f3f3f3f;
/*  因为天数最多只有100.所以我们直接从1模拟到n天。
    每天都检查一遍是不是有一场考试可以开始复习,若有则加入set。
    对于set的优先级我们将最终考试时间最早的那一场考试置于开头,
    那么这一场考试一定是当前时间最紧的一场,
    所以我们在没有考试的空闲日期里应该优先的复习最紧迫的一场考试。 */
int n,m;
int cnt[105];
int ans[105];
struct Node 
{
    int s,e,c,id;
    bool operator   < (const Node y) const 
     {
         return e<y.e;
     }
}a[105];
set<Node>s;
bool cmp(Node x,Node y)
{
    if(x.e!=y.e)
        return x.e<y.e;
    else
    {
        if(x.s!=y.s)
            return x.s<y.s;
        else
        {
            return x.id<y.id;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].c);
        a[i].id=i;
        ans[a[i].e]=m+1;
    }
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[j].s==i)
                s.insert(a[j]);
        }
        if(ans[i]!=0)
        {
            if(!s.empty()&&s.begin()->e==i)
            {
                cout<<-1<<endl;
                return 0;
            }
        }
        else if(s.empty())
        {
            ans[i]=0;
        }
        else
        {
            ans[i]=s.begin()->id;
            cnt[s.begin()->id]++;
            if(cnt[s.begin()->id]==s.begin()->c)
                s.erase(s.begin());
        }
    }
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    cout<<endl;
    getchar();
    getchar();
}


                                                                           ——时间划过风的轨迹,那个少年,还在等你。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值