51NOD 1467 旋轉繩 二分查找 模擬

題目來源: CodeForces
基準時間限制:1.5 秒 空間限制:131072 KB 分值: 80 難度:5級算法題
 收藏
 關注

平面上有n個釘子,他們從1到n編號,第i個釘子的座標是 (xi, 0)。然後我們我們把一個長度爲L,帶重物的繩子繫到第i個釘子上(那麼重物所在的座標是(xi, -L))。然後用力將重物向右推,開始逆時針旋轉。同時,如果旋轉的過程中碰到其它的釘子,就會繞着那個釘子旋轉。假設每個釘子都很細,重物繞着它旋轉時,不影響到繩子的長度。


更一般的,如果繩子碰到多個釘子,那麼它會繞着最遠的那個釘子轉。特殊的,如果繩子的末端碰到了一個釘子,那麼也會繞着那個釘子以長度爲0的繩子在轉。

經過一段時間之後,重物就會一直繞着某個釘子轉。

現在有m個查詢,每個查詢給出初始的繩子長度以及掛在哪個釘子下旋轉,請找出重物最終會繞哪個釘子旋轉。

樣例解釋:


Input
單組測試數據。
第一行包含兩個整數n 和 m (1 ≤ n, m ≤ 2*10^5),表示釘子的數目以及查詢的數目。
接下來一行包含n個整數 x1, x2, ..., xn ( -10^9 ≤ xi ≤ 10^9),表示每個釘子的座標。保證輸入的釘子的座標兩兩不相同。
接下來m行給出查詢。每行給出ai (1 ≤ ai ≤ n) 和 li(1 ≤ li ≤ 10^9),表示該查詢的重物掛在第ai個釘子上,繩子長度是li。
Output
輸出m行,第i行輸出第i個查詢的重物最終繞着哪個釘子轉。
二分查找釘子然後加了點優化..


#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int ok(long long x);
struct node
{
	long long data;
	int id;
};
bool cmp(node x,node y)
{
	return x.data<y.data;
}
node s[200003];
long long s1[200003]={0};
int n=0,m=0;
int jilv[3]={0};
int t=0; 
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(int i=1;i<=n;i++)
		 {
		 	scanf("%lld",&s[i].data);
		 	s[i].id=i;
		 	s1[i]=s[i].data;
		 }
		sort(s+1,s+n+1,cmp);
		t=0;
		while(m--)
		{
			int x=0,r=0;
			t=0;
			cin>>x>>r;
			x=ok(s1[x]);
			int end=0;
			int sum=0;
			jilv[t++]=x;
			if(s[x].data+r<s[x+1].data||x==n) sum++;
            while(1)
            {
            	int y=0;
               if(sum%2==0)
			   {
			   	   y=ok(s[x].data+r);
			   	   if(s[x].data+r==s[y].data)
			   	   {
			   	   	  end=y;
			   	   	  break;
				   }
				   else if(s[x].data==s[y].data)
				   {
				   	  end=y;
				   	  break;
				   }
				   else
				   {
				   	  r=r-(s[y].data-s[x].data);
				   	  x=y;
				   }
				   sum++;
				   if(t<2)
				   {
				   	jilv[t++]=x;
				   }
				   else
				   {
				   	  if(jilv[0]==x)
				   	  {
				   	  	 int R=abs(s[jilv[0]].data-s[jilv[1]].data);
				   	  	 int p=r/(R);
				   	  	 if(p&1)
				   	  	 {
				   	  	 	r=r-p*R;
				   	  	 	x=jilv[1];
				   	  	 	jilv[0]=x;
				   	  	 	t=1;
				   	  	 	sum++;
						 }
						 else
						 {
						 	r=r-p*R;
						 	t=1;
						 }
					  }
					  else
					  {
					  	jilv[0]=jilv[1];
					  	jilv[1]=x;
					  }
				   }
			   }
			   else
			   {   
					y=ok(s[x].data-r);
					if(y==0)
					{
				         r=r-(s[x].data-s[1].data);
				         x=1;
				         sum++;
				    if(t<2)
				   {
				   	jilv[t++]=x;
				   }
				   else
				   {
				   	  if(jilv[0]==x)
				   	  {
				   	  	 int R=abs(s[jilv[0]].data-s[jilv[1]].data);
				   	  	 int p=r/(R);
				   	  	 if(p&1)
				   	  	 {
				   	  	 	r=r-p*R;
				   	  	 	x=jilv[1];
				   	  	 	jilv[0]=x;
				   	  	 	t=1;
				   	  	 	sum++;
						 }
						 else
						 {
						 	r=r-p*R;
						 	t=1;
						 }
					  }
					  else
					  {
					  	jilv[0]=jilv[1];
					  	jilv[1]=x;
					  }
				   }
				         continue;
					}
					if(s[x].data-r==s[y].data)
					{
						end=y;
						break;
					}
					else if(s[x].data==s[y+1].data)
					{
						end=x;
						break;
					}
					else
					{
						r=r-(s[x].data-s[y+1].data);
						x=y+1;
					}
					sum++;
				   if(t<2)
				   {
				   	jilv[t++]=x;
				   }
				   else
				   {
				   	  if(jilv[0]==x)
				   	  {
				   	  	 int R=abs(s[jilv[0]].data-s[jilv[1]].data);
				   	  	 int p=r/(R);
				   	  	 if(p&1)
				   	  	 {
				   	  	 	r=r-p*R;
				   	  	 	x=jilv[1];
				   	  	 	jilv[0]=x;
				   	  	 	t=1;
				   	  	 	sum++;
						 }
						 else
						 {
						 	r=r-p*R;
						 	t=1;
						 }
					  }
					  else
					  {
					  	jilv[0]=jilv[1];
					  	jilv[1]=x;
					  }
				   }
			   }
			}
			printf("%d\n",s[end].id);
		}
	}
	return 0;
}
int ok(long long x)
{
	int u1=1,u2=n;
	int mid=0;
	while(u1<=u2)
	{
		mid=(u1+u2)/2;
	    if(s[mid].data<x)
	    {
	    	u1=mid+1;
		}
		else if(s[mid].data>x)
		{
			u2=mid-1;
		}
		else
		{
			return mid;
		}
	}
	return u2;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章