codeforces 961D Pair Of Lines

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

题意:给你n个二维坐标点,xi,yi的绝对值在1e9以内,然后问你能不能用两条直线穿过所有点。可以输出YES,不可以输出NO。

分析:当n<=4时,我们知道肯定是输出YES的。当n>4时,如果一条之间可以直接穿过所有点,那么就直接输出YES,否则选不共线的三个点,可以确定三条直线。比如选取1,2,3三个点,那么我们以1和2确定一条直线,判断这个n个点,如果有某个点不在这条直线上,我们就让他和3重新构成一条直线。如果这两条直线能穿过所有点,那么久输出YES,如果没能穿过所有点,我们就枚举剩下的情况,分别以1,3和2,3来当初始确定的直线。如果这三种情况都不可以,那么就输出NO。判断点在直线上应该比较简单,这里就不细说了。

AC代码:

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 struct st{
  6     long long x,y;
  7 }a[100005];
  8 int n;
  9 int judge(int c1,int c2,int c3){
 10     long long x1=a[c2].x-a[c1].x;
 11     long long y1=a[c2].y-a[c1].y;
 12     long long x2=0;
 13     long long y2=0;
 14     long long d=__gcd(x1,y1);
 15     x1/=d;
 16     y1/=d;
 17     if(x1<0){
 18         x1*=-1;
 19         y1*=-1;
 20     }
 21     int ans1=0,ans2=0;
 22     for(int i=1;i<=n;i++){
 23         if(i!=c1&&i!=c2&&i!=c3){
 24             long long x3=a[i].x-a[c1].x;
 25             long long y3=a[i].y-a[c1].y;
 26             long long x4,y4;
 27             if(x2!=0||y2!=0){
 28                 x4=a[i].x-a[c3].x;
 29                 y4=a[i].y-a[c3].y;
 30                 d=__gcd(x4,y4);
 31                 x4/=d;
 32                 y4/=d;
 33                 if(x4<0){
 34                     x4*=-1;
 35                     y4*=-1;
 36                 }
 37             }
 38             d=__gcd(x3,y3);
 39             x3/=d;
 40             y3/=d;
 41             if(x3<0){
 42                 x3*=-1;
 43                 y3*=-1;
 44             }
 45             //cout<<i<<endl;
 46            // cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<" "<<x3<<" "<<y3<<" "<<x4<<" "<<y4<<endl;
 47             if(x3==x1&&y3==y1){
 48                 ans1++;
 49             }
 50             else if(x2==0&&y2==0){
 51                 x2=a[i].x-a[c3].x;
 52                 y2=a[i].y-a[c3].y;
 53                 d=__gcd(x2,y2);
 54                 x2/=d;
 55                 y2/=d;
 56                 if(x2<0){
 57                     x2*=-1;
 58                     y2*=-1;
 59                 }
 60             }
 61             else if(x4==x2&&y4==y2){
 62                 ans2++;
 63             }
 64             else return 0;
 65         }
 66     }
 67     return n;
 68 }
 69 int main(){
 70     ios_base::sync_with_stdio(0);
 71     cin.tie(0);
 72     cin>>n;
 73     for(int i=1;i<=n;i++){
 74         cin>>a[i].x>>a[i].y;
 75     }
 76     if(n<=4){
 77         cout<<"YES"<<endl;
 78         return 0;
 79     }
 80     long long x1,y1,d,ans=-1;
 81     x1=a[2].x-a[1].x;
 82     y1=a[2].y-a[1].y;
 83     d=__gcd(x1,y1);
 84     x1/=d;
 85     y1/=d;
 86     if(x1<0){
 87         x1*=-1;
 88         y1*=-1;
 89     }
 90     for(int i=3;i<=n;i++){
 91          long long x2=a[i].x-a[1].x;
 92          long long y2=a[i].y-a[1].y;
 93          d=__gcd(x2,y2);
 94          x2/=d;
 95          y2/=d;
 96          if(x2<0){
 97             x2*=-1;
 98             y2*=-1;
 99          }
100          if(x2!=x1||y1!=y2){
101             ans=i;
102             break;
103          }
104     }
105     if(ans==-1){
106         cout<<"YES"<<endl;
107         return 0;
108     }
109     d=-1;
110     d=judge(1,2,ans);
111     if(d==n){
112         cout<<"YES"<<endl;
113         return 0;
114     }
115     d=judge(2,ans,1);
116     if(d==n){
117         cout<<"YES"<<endl;
118         return 0;
119     }
120     d=judge(1,ans,2);
121     if(d==n){
122         cout<<"YES"<<endl;
123         return 0;
124     }
125     cout<<"NO"<<endl;
126 return 0;
127 }
View Code

 

转载于:https://www.cnblogs.com/ls961006/p/8782688.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CodeForces - 616D是一个关于找到一个序列中最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段中不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]中不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当前数字在map中不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]中的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值