zoukankan      html  css  js  c++  java
  • CF555D Solution

    题目链接

    题解

    模拟,每次二分找下一个钉子,将绳子整除其间距离即可。

    Q:时间复杂度为什么是正确的呢?为什么不会出现每次找下一个钉子都恰好只够一个距离的情况(这样单次查询时间为(O(n)))?

    A:因为出题人不够毒瘤。假设已经找到了第(i-1)和第(i)根钉子,要想构造上述情况,第(i+1)根钉子最优位置是(i,i-1)两根钉子的中点(感性理解可知无论是左偏还是右偏都会使剩余绳长减小)。而这时最多只有(log(2 imes 10^9))个钉子,(O(n))查询完全可以通过。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    int x[N],z[N],n;
    struct node {int v,id;} y[N];
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	while(ch<'0' || ch>'9') {if(ch=='-') w=-1; ch=getchar();}
    	while(ch>='0' && ch<='9') s=s*10+ch-'0',ch=getchar();
    	return s*w;
    }
    bool cmp(node a,node b) {return a.v<b.v;}
    int solve(int a,int l,bool op)
    {
    	int r,tmp;//1:->,0:<-
    	if(op) r=y[upper_bound(z+1,z+n+1,x[a]+l)-z-1].id;
    	else r=y[lower_bound(z+1,z+n+1,x[a]-l)-z].id;
    	if(r==a) return a;
    	bool qwq=(l/abs(x[r]-x[a]))%2;//1:相反,0:相同 
    	l%=abs(x[r]-x[a]);
    	if(qwq) return solve(r,l,op^1);
    	else return solve(a,l,op);
    }
    int main()
    {
    	n=read(); int m=read(),a,l;
    	for(int i=1;i<=n;i++) x[i]=y[i].v=z[i]=read(),y[i].id=i;
    	sort(y+1,y+n+1,cmp),sort(z+1,z+n+1);
    	while(m--)
    	{
    		a=read(),l=read();
    		int r=y[upper_bound(z+1,z+n+1,x[a]+l)-z-1].id;
    		l-=(x[r]-x[a]);
    		printf("%d
    ",solve(r,l,0));
    	}
    	return 0;
    }
    
  • 相关阅读:
    用导数解决逗逼初三数学二次函数图像题
    NOIP 2014 pj & tg
    BZOJ 1004
    双参数Bellman-ford带队列优化类似于背包问题的递推
    emu1
    無題
    15 day 1代碼
    javascript quine
    线段树的总结
    Watering the Fields(irrigation)
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14993406.html
Copyright © 2011-2022 走看看