Codeforces Round #558 (Div. 2) (还差3题)

算得上第一次好好写Codeforce吧,总体感受,题目很灵活,我英语很菜,读题1小时,写题半小时; 

总结:对于想B题这种的题目,如何判断条件,f数组不难想,rf数组还是要想一下的; 

      对于C,计算几何知识基本空白...需要补一下; 

 题目链接:https://codeforces.com/contest/1163

A:

签到,直接推个公式就行,注意0的时候要特判一下。 

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    //freopen("in.txt", "r", stdin);
    int n, a;
    //while(cin>>n>>a)
    cin>>n>>a;
    {
        if(a==0)
            cout<<"1"<<endl;
        else if(a<=(n/2))
            cout<<a<<endl;
        else
            cout<<n-a<<endl;
    }
    return 0;
}
View Code

 

B(1,2):

题意:给出n天对应的颜色,求一个长度为x的前缀满足从前面x天中能够去除一天使得剩余的x-1的天中,每种颜色的天数相同(英语太菜了...应该大概就这意思吧)

   数据范围天数<10^5, 颜色的种类数<=10^5; 

题解:满足条件的前x天可以划分成4种情况:

   1.只有一种颜色

   2.每种颜色只有1天

   3.其中一种颜色有一天,其他种类的颜色相等

   4.其中一种颜色比其他的颜色多一(其他的颜色数目相等)

想要对这四种情况做出判定只要维护: f [i] 第i种颜色出现的次数, rf[i] 出现 i 次的颜色 的种类, max_num 前i天的的最大f[k] (k<=i) 就是某种颜色出现最多的次数; 

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

const int maxn=1e5+5;
int col, f[maxn], rf[maxn];
/// f是某种颜色出现的次数; rf是某种颜色出现i次的颜色种类数目;

int main()
{
    int n; cin>>n;
    int col, num_max=0, ans=0;  ///num_max维护的是某种颜色出现的最大次数
    for(int i=1; i<=n; i++)
    {
        cin>>col;
        rf[f[col]]--;
        rf[++f[col]]++;
        num_max=max(num_max, f[col]);

        if(rf[i]==1) ans=i; ///只有一种颜色(出现了i次)
        else if(rf[1]==i) ans=i; ///每种颜色只出现一次
        else if(rf[1]==1 && rf[num_max]*num_max==i-1) ans=i; ///有一种出现了1次,其他的出现了相同的次数
        else if(rf[num_max-1]*(num_max-1)==i-num_max && rf[num_max]==1) ans=i; ///有一种多出现了一次,其他的出现相同次数
    }
    printf("%d\n", ans);  
    return 0;
}
View Code

 

C(1,2):

题意:给出n个点的坐标,求这n个所形成的直线(同一条只算一条)中有多少组(2个一组)是相交的

题解:就是用一个map<pair<int, int>, set<long long>> slope_map 维护即可 

   分别是直线ax+by=c,中的a,b,c; 

   不平行的就是相交,注意要去除重复的直线; 

总结:注意数据范围 截距一定要用long long 存; 

   对于经过(x1, y1), (x2, y2) 的直线 ax+by=c来说

   a=y1-y2,  b=x1-x2 ; 

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

const int MAXN=1010;
int x[MAXN], y[MAXN];
map<pair<int,int>, set<long long>> slope_map;


int gcd(int a, int b){
    if(a==0) return b;
    return gcd(b%a, a);
}

int main()
{
    int n; cin>>n;
    for(int i=1; i<=n; i++)
        cin>>x[i]>>y[i];

    long long ans=0, all_line=0;
    for(int i=1; i<n; i++)
        for(int j=i+1; j<=n; j++)
        {
            int x1 = x[i], y1 = y[i], x2 = x[j], y2 = y[j];
            int a=y1-y2, b=x1-x2;
            int g=gcd(a, b);
            a/=g;  b/=g;
            if(a<0 || (a==0 && b<0))
                a=-a, b=-b;
            pair<int, int> slope(a,b);
            long long c=(long long)a*x[i]-(long long)b*y[i];
            if(!slope_map[slope].count(c))
            {
                ans+=all_line-slope_map[slope].size();
                all_line++;
                slope_map[slope].insert(c);
            }
        }
        printf("%I64d\n", ans);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Yokel062/p/10877026.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值