zoukankan      html  css  js  c++  java
  • 【NOIP2012提高组】开车旅行

    这题倍增。
    当拿到a数组时,我们便记录他的位置并排个序(再用一个数组)
    然后,我们就将其变成一个链表的样子。
    由于题目要求每次这能从左边走到右边,
    所以我们便从1开始枚举到n,

    设nx[i][j]表示从i走2j步所到达的点

    f[i][j][0/1]表示到达A/B所走的路程

    (一步表示A一天+B一天)

    PS:luogu的也A了
    上标:

    #include<cstdio>
    #include<algorithm>
    #define ll long long
    #define N 100010
    using namespace std;
    ll nx[N][19],f[N][19][2],cl[N][2];
    int n,X,m,a[N],b[N],c[N],l[N],r[N],s,x;
    ll A,B,fr=0,mA=(1<<30),mB=1;
    
    inline int read()
    {
    	int x=0,f=0; char c=getchar();
    	while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
    	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return f ? -x:x;
    }
    
    void qsort(int l,int r)
    {
    	int i=l,j=r,mid=c[l+r>>1],mid1=b[l+r>>1];
    	while (i<j)
    	{
    		while (c[i]<mid || (c[i]==mid && b[i]<mid1)) i++;
    		while (c[j]>mid || (c[j]==mid && b[j]>mid1)) j--;
    		if (i<=j)
    		{
    			swap(c[i],c[j]);
    			swap(b[i],b[j]);
    			i++,j--;
    		}
    	}
    	if (i<r) qsort(i,r);
    	if (l<j) qsort(l,j);
    }
    
    void jump(int x,int s)
    {
    	A=0,B=0;
    	for (int i=16;i>=0;i--)
    		while (nx[x][i] && A+B+f[x][i][0]+f[x][i][1]<=s)
    				A+=f[x][i][0],B+=f[x][i][1],x=nx[x][i];
    	if (cl[x][1] && A+B+abs(a[cl[x][1]]-a[x])<=s) A+=abs(a[cl[x][1]]-a[x]);
    }
    
    int main()
    {
    	freopen("drive.in","r",stdin);
    	freopen("drive.out","w",stdout);
    	n=read();
    	for (int i=1;i<=n;i++) c[i]=a[i]=read(),b[i]=i;
    	qsort(1,n);
    	for (int i=1;i<=n;i++) l[b[i]]=b[i-1],r[b[i]]=b[i+1];
    	for (int i=1;i<=n;i++)
    	{
    		if (!l[i] && !r[i]) continue;
    		if (!l[i]) cl[i][0]=r[i],cl[i][1]=r[r[i]],l[r[i]]=0;
    		else if (!r[i]) cl[i][0]=l[i],cl[i][1]=l[l[i]],r[l[i]]=0;
    		else
    		{
    			if (abs(a[i]-a[l[i]])==abs(a[i]-a[r[i]]))
    			{
    				if (a[l[i]]<a[r[i]])
    				{
    					cl[i][0]=l[i],cl[i][1]=r[i];
    					r[l[i]]=r[i],l[r[i]]=l[i];
    				}
    				else
    				{
    					cl[i][0]=r[i],cl[i][1]=l[i];
    					r[l[i]]=r[i],l[r[i]]=l[i];
    				}
    			}
    			else if (abs(a[i]-a[l[i]])<abs(a[i]-a[r[i]]))
    			{
    				cl[i][0]=l[i];
    				if (!l[l[i]]) cl[i][1]=r[i];
    				else if (abs(a[i]-a[l[l[i]]])==abs(a[i]-a[r[i]]) && a[l[l[i]]]<a[r[i]]) cl[i][1]=l[l[i]];
    				else if (abs(a[i]-a[l[l[i]]])<abs(a[i]-a[r[i]])) cl[i][1]=l[l[i]];
    				else cl[i][1]=r[i];
    				r[l[i]]=r[i],l[r[i]]=l[i];
    			}
    			else
    			{
    				cl[i][0]=r[i];
    				if (!r[r[i]]) cl[i][1]=l[i];
    				else if (abs(a[i]-a[r[r[i]]])==abs(a[i]-a[l[i]]) && a[r[r[i]]]<a[l[i]]) cl[i][1]=r[r[i]];
    				else if (abs(a[i]-a[r[r[i]]])<abs(a[i]-a[l[i]])) cl[i][1]=r[r[i]];
    				else cl[i][1]=l[i];
    				r[l[i]]=r[i],l[r[i]]=l[i];
    			} 
    		}
    	}
    	for (int i=1;i<=n;i++)
    	{
    		nx[i][0]=cl[cl[i][1]][0];
    		if (cl[i][1])
    		{
    			f[i][0][0]=abs(a[cl[i][1]]-a[i]);
    			if (nx[i][0])
    				f[i][0][1]=abs(a[nx[i][0]]-a[cl[i][1]]);
    		}
    	}
    	for (int j=1;j<=16;j++)
    		for (int i=1;i<=n;i++)
    		{
    			nx[i][j]=nx[nx[i][j-1]][j-1];
    			f[i][j][0]=f[i][j-1][0]+f[nx[i][j-1]][j-1][0];
    			f[i][j][1]=f[i][j-1][1]+f[nx[i][j-1]][j-1][1]; 
    		}
    	X=read();
    	for (int i=1;i<=n;i++)
    	{
    		jump(i,X);
    		if (!B) continue;
    		if ((double)mA/mB>(double)A/B)
    			mA=A,mB=B,fr=i;
    	}
    	printf("%d
    ",fr);
    	m=read();
    	for (int i=1;i<=m;i++)
    	{
    		s=read(),x=read(),jump(s,x);
    		printf("%lld %lld
    ",A,B);
    	}
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    POJ 1015 Jury Compromise【DP】
    POJ 1661 Help Jimmy【DP】
    HDU 1074 Doing Homework【状态压缩DP】
    HDU 1024 Max Sum Plus Plus【DP,最大m子段和】
    占坑补题。。最近占的坑有点多。。。
    Codeforces 659F Polycarp and Hay【BFS】
    Codeforces 659E New Reform【DFS】
    Codeforces 659D Bicycle Race【计算几何】
    廖大python实战项目第四天
    廖大python实战项目第三天
  • 原文地址:https://www.cnblogs.com/jz929/p/11817666.html
Copyright © 2011-2022 走看看