<QluOJ2018NewCode>计算几何(寄蒜几盒)

题目描述

现在有一个圆圈,圆圈上有若干个点,请判断能否在若干个点中选择三个点两两相连组成一个等边三角形?
这若干个点在圆圈上按顺时针顺序分布。
如果可以的话输出"Yes"(不含引号)
不可以的话输出"No"(不含引号)

 

输入

第一行一个整数n,表示圆圈上有n个点
第二行n个整数,分别表示第1个点与第2个点之间圆弧的长度、第2个点与第3个点之间圆弧的长度······第n个点与第1个点之间圆弧的长度
3 <= n <= 10^6
1 <= x_i <= 1000 ( 1 <= i <= n)

 

输出

如果可以组成等边三角形则输出"Yes"(不含引号)
否则输出"No"(不含引号)

 

样例输入

样例输入1:
4
1 1 2 2

样例输入2:
8
4 2 4 2 2 6 2 2

 

样例输出

样例输入1:
Yes

样例输入2:
Yes

 

提示

对于样例2配图:
  
 
 
思路:
可以把圆看成一条线,解法算是二分+前缀和。
如果里面有等边三角形,也就是说圆弧能等分成三份,于是第一个判断条件就是:
1)周长%3==0
那么,三角形的边长就是周长/3,所以三个点假设为a,b,c,三个点到1号点的距离就分别是:xa,xa+t,xa+t+t,其中t=周长/3。
2)查找xa,xa+t,xa+2t是否存在(二分)
 
 
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int a[1000005];
int x[1000010];
int n;
bool find(int mis,int left,int right){
    while(left+1<right){
        int mid=(left+right)/2;
        if(x[mid]==mis){
            return true;
        }else{
            if(x[mid]<mis){
                left=mid;
            }else{
                right=mid;
            }
        }
    }
    return false;
}
bool check(int t){
    for(int i=0;i<=n-2;i++){//因为最少三个点嘛
        int p1=x[i]+t;
        int p2=x[i]+2*t;
        if(find(p1,0,n)==true&&find(p2,0,n)==true){
            return true;
        }
    }
    return false;
    
}
int main(){
    cin>>n;
    x[0]=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        x[i]=x[i-1]+a[i];
    }
    if(x[n]%3!=0){
        cout<<"No"; 
    }else{
        if(check(x[n]/3)==true){
            cout<<"Yes";
        }else{
            cout<<"No";
        }
    }
    return 0;
} 

 

posted @ 2018-11-28 19:20  Fylsea  阅读(256)  评论(0编辑  收藏  举报