标签:端点 blog 避免 而且 多次 als cto 题目 思路
题目大意:
一个直线上有n个钉子,现在分别在某个钉子上挂一段系有重物的绳子,对这个物体是加一个向右的力,使它作圆周运动,
绳子最终一定会缠在一些钉子上并围绕某一个钉子做圆周运动。
问最终会围哪个钉子做运动。
思路:
考虑暴力模拟,每次二分查找绳子会转到哪里,并对绳子减去区间的长度,这样能拿到10分。
显然绳子有些时候会在同样一段区间上转很多次,因此我们可以取模避免重复减,这样能拿到30分。
观察发现每次绳子能够旋转的范围是在不断缩减的,而且左端点越来越大,右端点越来越小,这样我们可以每次缩减一下二分的范围,这样就能拿到100分。
注意第一次旋转时不能直接取模。
1 #include<cstdio> 2 #include<cctype> 3 #include<vector> 4 #include<algorithm> 5 inline int getint() { 6 register char ch; 7 register bool neg=false; 8 while(!isdigit(ch=getchar())) if(ch==‘-‘) neg=true; 9 register int x=ch^‘0‘; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^‘0‘); 11 return neg?-x:x; 12 } 13 const int N=200001; 14 struct Point { 15 int x,id; 16 bool operator < (const int &another) const { 17 return x<another; 18 } 19 bool operator < (const Point &another) const { 20 return x<another.x; 21 } 22 }; 23 std::vector<Point> v; 24 int x[N]; 25 int main() { 26 const int n=getint(); 27 int m=getint(); 28 for(register int i=1;i<=n;i++) { 29 v.push_back((Point){x[i]=getint(),i}); 30 } 31 std::sort(v.begin(),v.end()); 32 while(m--) { 33 std::vector<Point>::iterator b=v.begin(),e=v.end(); 34 int last=0,i=getint(),l=getint(); 35 bool d=true; 36 last=i; 37 e=std::lower_bound(b,e,x[i]+l+1); 38 i=(e-1)->id; 39 l-=x[i]-x[last]; 40 if(last==i) { 41 last=i; 42 b=std::lower_bound(b,e,x[i]-l); 43 i=b->id; 44 l-=x[last]-x[i]; 45 } 46 while(last!=i) { 47 if(d) { 48 last=i; 49 e=std::lower_bound(b,e,x[i]+l+1); 50 i=(e-1)->id; 51 if(i==last) { 52 d^=true; 53 goto Left; 54 } 55 if((l/(x[i]-x[last]))&1) { 56 d^=true; 57 } else { 58 std::swap(last,i); 59 } 60 l%=x[i]-x[last]; 61 } 62 Left: 63 if(!d) { 64 last=i; 65 b=std::lower_bound(b,e,x[i]-l); 66 i=b->id; 67 d^=true; 68 l-=x[last]-x[i]; 69 } 70 } 71 printf("%d\n",i); 72 } 73 return 0; 74 }
标签:端点 blog 避免 而且 多次 als cto 题目 思路
原文地址:http://www.cnblogs.com/skylee03/p/7600473.html