zoukankan      html  css  js  c++  java
  • codeforces #310 div1 D

    一开始写了个暴力模拟绳子的摆动轨迹

    然后在Test 16 T掉了

    后来%了一下别人的代码,发现需要对特殊情况进行特殊处理

    首先我们考虑绳子的向右摆动,设当前位置为p,绳子当前长度为L

    如果其旋转中心位置>p+L/2,那么绳子长度至少会缩短一半

    假设一直这样下去,时间复杂度为log(L)

    但是当旋转中心位置<p+L/2的时候就比较复杂了,我们发现暴力模拟很容易被卡成单次O(L)

    因为这个时候会出现绳子不断地在两个点之间转来转去,每次减少绳长很少

    但是我们又会发现挡在两个点之间旋转时候,转一圈减少的长度为2*(p1-p2)

    那么不断的在两个点之间旋转我们只需要令L=L%(2*(p1-p2)) 即可

    这样就不会被卡成O(L)了

    至于对最后答案的判定,我们只需要旋转两次,如果这两次旋转中心相同,证明这就是答案

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxn=200010;
    int n,m,now,len;
    int a[maxn];
    int idx[maxn];
    int p[maxn];
    
    bool cmp(const int &u,const int &v){return a[u]<a[v];}
    int Rotate(int id,int L,int f){
    	if(f==1)return upper_bound(a+1,a+n+1,a[id]+L)-a-1;
    	else return lower_bound(a+1,a+n+1,a[id]-L)-a;
    }
    int Get_ans(int id,int L,int f){
    	int n1=Rotate(id,L,f);
    	int n2=Rotate(n1,L-abs(a[n1]-a[id]),f^1);
    	if(n2==id){
    		if(id==n1)return id;
    		int d=2*abs(a[id]-a[n1]);
    		return Get_ans(id,L%d,f);
    	}else Get_ans(n1,L-abs(a[n1]-a[id]),f^1);
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)scanf("%d",&a[i]),idx[i]=i;
    	sort(idx+1,idx+n+1,cmp);sort(a+1,a+n+1);
    	for(int i=1;i<=n;++i)p[idx[i]]=i;
    	while(m--){
    		scanf("%d%d",&now,&len);
    		printf("%d
    ",idx[Get_ans(p[now],len,1)]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    OC中ARC forbids explicit message send of release错误
    OC中内存管理(转)
    [题解]数学期望_luogu_P1850_换教室
    [题解](单调队列)luogu_P2216_BZOJ_1047 理想的正方形
    [题解]luogu_AT1224_JOIOJI
    [题解]区间dp_luogu_P3147 262144
    [筆記]歐拉路
    [題解/狀壓dp]POJ_2411_Mondriaan's dream
    [題解]luogu_P1854 花店櫥窗佈置
    [題解]luogu_P1052 過河
  • 原文地址:https://www.cnblogs.com/joyouth/p/5368873.html
Copyright © 2011-2022 走看看