P1081 (倍增+代码实现技巧)

在写提前先花一点时间想好自己的代码里有什么,这样就不用像我这样调一天了。然后在遇到比较相似的代码时,可以考虑并到一个函数里,比如说push_up和getsum里对左区间和右区间的合并,我一般是写在一个函数里的qwq。

在调了超过2h时可以考虑重复上面的过程(重构在思路清晰的情况下是很快的,反正我重构只花了1h)

这题其实还是比较简单的,有点像大模拟。思路非常简单。在看到对一个静态的区间求max/min时我们可以想到使用RMQ,在看到对一个静态的区间求(任何具有结合律的运算,像和,max/min(虽然时间复杂度不优),矩阵乘法,快速幂)时可以想到倍增,而带修时,就想到各种ds了。

看到对数组中两个数的abs取min,并且是有顺序的,可以考虑平衡树(我不会链表qwq)

好讲完这题思路的来源就可以放代码了

#include<bits/stdc++.h>
using namespace std;
struct grg{
	long long val,id;
	bool g;
}g[7];
bool cmp(grg x,grg y){
	if(x.val==y.val) return x.g<y.g;
	return x.val<y.val;
}
long long n,h[100005],x,T,s,dp[100005][20][2],tar[100005][2],atar[100005][20],btar[100005][20];//从i城市往前开2^i轮 
//-----------------fhq-treap-----------------------
struct node{
   long long val,rd;
}p[100005];
long long root,size[100005],son[100005][2],cnt=0,rx,ry,rz;
void update(long long rt){
    size[rt]=size[son[rt][0]]+size[son[rt][1]]+1;
}
long long add(long long x){
    cnt++;
    size[cnt]=1;
    p[cnt].val=x;
    p[cnt].rd=rand();
    return cnt;
}
void split(long long rt,long long key,long long &x,long long &y){
    if(!rt){
        x=y=0;
        return;
    }
    if(p[rt].val<=key){
        x=rt;
        split(son[rt][1],key,son[rt][1],y);
    }
    else{
        y=rt;
        split(son[rt][0],key,x,son[rt][0]);
    }
    update(rt);
}
void split1(long long rt,long long siz,long long &x,long long &y) {
    if(!rt){
        x=y=0;
        return;
    }if(size[son[rt][0]]>=siz){
        y=rt;
        split1(son[rt][0],siz,x,son[rt][0]);
    }else{
        x=rt;
        split1(son[rt][1],siz-(size[son[rt][0]]+1),son[rt][1],y);
    }
    update(rt);
}
long long merge(long long l,long long r){
    if(!l||!r) return l+r;
    if(p[l].rd<p[r].rd){
        son[l][1]=merge(son[l][1],r);
        update(l);
        return l;
    }else{
        son[r][0]=merge(l,son[r][0]);
        update(r);
        return r;
    }
}
long long getrnk(long long x,long long k){
	if(!x) return 0;
    while(true){
        if(k<=size[son[x][0]]) x=son[x][0];
        else if(k>size[son[x][0]]+1){
            k-=(size[son[x][0]]+1);
            x=son[x][1];
        }
        else return x;
    }
}
void insert(long long x){
    split(root,x,rx,ry);
    root=merge(merge(rx,add(x)),ry);
}//插入x
//-----------------fhq-treap-----------------------
bool eq(double x,double y){
	if(fabs(x-y)<=1e-6) return true;
	return false;
}
void solve(long long u,long long top,long long &x,long long &y){//起点 距离 A B 
	x=y=0;
	for(long long i=19;i>=0;i--){
		//cout<<u<<" "<<i<<":"<<dp[u][i][0]<<" "<<dp[u][i][1]<<"\n";
		if((dp[u][i][0]+dp[u][i][1]<=top)&&atar[u][i]){
			x+=dp[u][i][0];
			y+=dp[u][i][1];
			top-=(dp[u][i][0]+dp[u][i][1]);
			u=atar[u][i];
		}
	}
	if(tar[u][0]&&abs(h[u]-h[tar[u][0]])<=top) x+=abs(h[u]-h[tar[u][0]]);
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	srand(time(0));
	memset(dp,0x3f,sizeof(dp));
	cin>>n;
	for(long long i=1;i<=n;i++){
		cin>>h[i];
	}
	for(long long i=n;i>=1;i--){
		for(long long j=1;j<=4;j++) g[1].val=g[2].val=g[3].val=g[4].val=1e16;
		split(root,h[i],rx,ry);
		if(size[rx]>=2){
			g[1].id=n-getrnk(rx,size[rx]-1)+1;
			g[1].val=abs(h[g[1].id]-h[i]);
			if(h[g[1].id]<h[i]) g[1].g=0;
			else g[1].g=1;
		}if(size[rx]){
			g[2].id=n-getrnk(rx,size[rx])+1;
			g[2].val=abs(h[g[2].id]-h[i]);
			if(h[g[2].id]<h[i]) g[2].g=0;
			else g[2].g=1;
		}if(size[ry]){
			g[3].id=n-getrnk(ry,1)+1;
			g[3].val=abs(h[g[3].id]-h[i]);
			if(h[g[3].id]<h[i]) g[3].g=0;
			else g[3].g=1;
		}if(size[ry]>=2){
			g[4].id=n-getrnk(ry,2)+1;
			g[4].val=abs(h[g[4].id]-h[i]);
			if(h[g[4].id]<h[i]) g[4].g=0;
			else g[4].g=1;
		}
		root=merge(rx,ry);
		sort(g+1,g+5,cmp);
		if(g[1].val!=1e16) tar[i][1]=g[1].id;
		if(g[2].val!=1e16) tar[i][0]=g[2].id;
		insert(h[i]);
	}
	//tar[n][0]=tar[n][1]=n+1;
	for(long long i=1;i<=n;i++){
		if(tar[tar[i][0]][1]){
			dp[i][0][0]=abs(h[i]-h[tar[i][0]]);
			dp[i][0][1]=abs(h[tar[i][0]]-h[tar[tar[i][0]][1]]);
			atar[i][0]=tar[tar[i][0]][1];
		}
	}
	for(long long j=1;j<=19;j++){
		for(long long i=1;i<=n;i++){
			if(atar[atar[i][j-1]][j-1]){
				atar[i][j]=atar[atar[i][j-1]][j-1];
				dp[i][j][0]=dp[i][j-1][0]+dp[atar[i][j-1]][j-1][0];
				dp[i][j][1]=dp[i][j-1][1]+dp[atar[i][j-1]][j-1][1];
			}
		}
	}
	long long maxh=-1,ans=0;
	double minn=1e9;
	cin>>x;
	//solve(2,x,rx,ry);
	//cout<<rx<<"-"<<ry<<endl;
	for(long long i=1;i<=n;i++){
		solve(i,x,rx,ry);
		if(ry==0){
			if(eq(minn,1e9)){
				if(h[i]>maxh){
					maxh=h[i];
					ans=i;
				}
			}
		}else{
			if(eq((double)rx,(double)ry*minn)){
				if(h[i]>maxh){
					maxh=h[i];
					ans=i;
				}
			}else if((double)rx<(double)ry*minn){
				minn=(double)rx/(double)ry;
				maxh=h[i];
				ans=i;
			}
		}
	}
	cout<<ans<<"\n";
	cin>>T;
	while(T--){
		cin>>s>>x;
		solve(s,x,rx,ry);
		cout<<rx<<" "<<ry<<"\n";
	}
	
	return 0;
}
posted @ 2024-02-28 14:15  wuhupai  阅读(1)  评论(0编辑  收藏  举报