CF #113Div2

A. Rank List

大水题,求第K名有几人和它的分数一样,考察结构体排序

代码:

#include <iostream>
#include <cstring>
#include <map>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int M=50000;
struct node
{
    int pi,ti;
    int id;
} a[55];
int b[55];
bool cmp(node a,node b)
{
    if(a.pi==b.pi)
        return a.ti<b.ti;
    return a.pi>b.pi;
}
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=0; i<n; i++)
    {
        scanf("%d %d",&a[i].pi,&a[i].ti);
    }
    sort(a,a+n,cmp);
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(a[i].pi==a[k-1].pi && a[i].ti==a[k-1].ti)
        ans++;
    }
    printf("%d\n",ans);
    return 0;
}

B. Polygons

题意:给出两个凸多边形A、B,判断B是否严格在A凸多变形内,严格B不能和A有交点

凸包问题,WA了好多次,就是一个精度问题。。先进行特殊判断,先排序,只要发现有两个点相同,那肯定不符合

代码:

#include <iostream>//B
#include <cstring>
#include <map>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int M=100005;
struct node
{
    int x,y;
    int belong;
} a[2*M];
node stak[2*M];
int n,m;
bool cmp(node a,node b)
{
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}
long long  dis(node a,node b,node c)
{
    return (long long)(b.x-a.x)*(c.y-a.y)-(long long)(c.x-a.x)*(b.y-a.y);
    //return (b.x-a.x)*(c.y-b.y)-(c.x-b.x)*(b.y-a.y);
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
        a[i].belong=1;
    }
    scanf("%d",&m);
    for(int i=n+1; i<=m+n; i++)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
        a[i].belong=2;
    }
    sort(a+1,a+m+n+1,cmp);
    for(int i=2; i<=n+m; i++)
    {
        if(a[i].x==a[i-1].x && a[i].y==a[i-1].y)
        {
            cout<<"NO"<<endl;
            return 0;
        }
    }
    int s;
    stak[1]=a[1];
    stak[2]=a[2];
    s=2;
    for(int i=3; i<=n+m; i++)
    {
        while(s>1 && dis(stak[s-1],stak[s],a[i])<0)s--;
        stak[++s]=a[i];
    }
    int len = s;
    stak[++s] = a[n+m-1];
    for(int i = n+m-2; i >0; --i)
    {
        while(s!=len && dis(stak[s-1],stak[s],a[i])<0)s--;
        stak[++s]=a[i];
    }
    for(int i=1; i<=s; i++)
    {
        if(stak[i].belong==2)
        {
            cout<<"NO"<<endl;
            return 0;
        }
    }
    cout<<"YES"<<endl;
    return 0;
}



C. Median

题意:求应该在原数组里最少增加几个数是的所给X在原数组排序后处于中间mid=(n+1)/2处。。

这题还是得手动列一下,就会发现一些规律(还算得上吧),先看原数组里有没有X,没有有的话先加X到末尾在进行从小到大排序,找X的位置i,若i==mid,cnt=1;我们可以发现2*i<2*mid=n(n%2==0),2*i-1<2*mid-1=n(n%2==1),要使i为中心位置,就以i为中心取2*i个数,因为i<mid,右边肯定会多出几个数,为了平衡,应该也在左边多出和右边一样多的数,即cnt+=2*mid-2*i=n-2*i;同理:i>mid,2*i>2*mid,cnt+=2*i-2*mid-1=2*i-n-1,减1是为了是的所加数最小,举个例子5  和6,中心位置都是3,那我们就要5,也就是取奇数。

代码:

#include <iostream>
#include <cstring>
#include <map>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
int a[505];
int main()
{
    int n,x,i,ans=0;
    scanf("%d%d",&n,&x);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
    {
        if(a[i]==x)break;
    }
    if(i==n+1)
    {
        ans++;
        n++;
        a[n]=x;
    }
    sort(a+1,a+n+1);
    int mid=(n+1)>>1;
    if(a[mid]<x)
    {
        for(i=mid+1;i<=n;i++)
        {
            if(a[i]==x)break;
        }
        ans+=2*i-n-1;
    }
    if(a[mid]>x)
    {
        for(i=mid-1;i>=1;i--)
        if(a[i]==x)break;
        ans+=n-2*i;
    }
    cout<<ans<<endl;
    return 0;
}

E. Tetrahedron

推规律题,但是当时赛场上我就没有推出,有点拙了,附上一个DP的代码吧

#include <iostream>
#include <cstring>
#include <map>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int M=50000;
const int N=1e9+7;
int dp[10000007][4];
int main()
{
   dp[0][0]=1;
   int n;
   cin>>n;
   for(int i=1;i<=n;i++)
   {
       dp[i][0]=(dp[i-1][1]+(dp[i-1][2]+dp[i-1][3])%N)%N;
       dp[i][1]=(dp[i-1][0]+(dp[i-1][2]+dp[i-1][3])%N)%N;
       dp[i][2]=(dp[i-1][0]+(dp[i-1][1]+dp[i-1][3])%N)%N;
       dp[i][3]=(dp[i-1][0]+(dp[i-1][1]+dp[i-1][2])%N)%N;
   }
   cout<<dp[n][0]<<endl;
    return 0;
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值