Luogu P7167

Detailed explanation of Luogu P7167 fountain problem

The problem portal I
just learnt doubled, this problem is blank when I do homework at night, it will be violent, and I will do the next problem after eating 30 points of the minimum guarantee.

The brute force code is as follows:

#include<bits/stdc++.h>
using namespace std;
struct mint
{
    
    
	int d,c;
}p[100005];
int main()
{
    
    
	int n,q,r,v;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
    
    
		scanf("%d%d",&p[i].d,&p[i].c);
	}
	while(q--)
	{
    
    
		scanf("%d%d",&r,&v);
		bool flag=0;
		int tot=v;
		int max=0;
		for(int i=r;i<=n;i++)
		{
    
    
			if(p[i].d>max)
			{
    
    
				tot-=p[i].c;
				max=p[i].d;
			}
			if(tot<=0)
			{
    
    
				flag=1;
				printf("%d\n",i);
				break;
			}
		}
		if(flag==0)
		{
    
    
			printf("0\n");
		}
	}
	return 0;
}

The next day in class, after listening to the big guys,
we started talking. We used the dp[i][j] array to represent the point i, and jumped backward by 2^j steps to the point. (Multiplication thought)
Preprocessing dp[i][j]:
dp[i][0] = nxt[i];
So what is this nxt[i]?
The nxt[] array is used to store where the water in each disk will eventually flow to

5 4 6 7 2 9 4    d[i]
3 3 4 6 6 0 0    nxt[i]
这里的nxt[]存的是每个圆盘的位置``

Preprocess the nxt[] array:

int solve1(int x)
{
    
    
	if(!top) 
	{
    
    
		return 0;
	}
	int L=1,R=top;
	while(L<R)
	{
    
    
		int mid=(L+R+1)>>1;
		if(st[mid]>x)
		{
    
    
			L=mid;
		}
		else R=mid-1;
	}
	return st[L]>x?pos[L]:0;
}

Then we use the sum[i][j] array to store the point i, and jump backward by 2^j steps to the point. The sum of the capacities of these discs (not including the point i) and
finally spell them together to write a double Is the complete code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int N=17;
int n,Q,d[maxn],c[maxn];
int nxt[maxn];
int st[maxn],pos[maxn],top=0;
int solve1(int x)
{
    
    
	if(!top) 
	{
    
    
		return 0;
	}
	int L=1,R=top;
	while(L<R)
	{
    
    
		int mid=(L+R+1)>>1;
		if(st[mid]>x)
		{
    
    
			L=mid;
		}
		else R=mid-1;
	}
	return st[L]>x?pos[L]:0;
}
int dp[maxn][N+2];
ll sum[maxn][N+2];
void init()
{
    
    
	for(int i=n;i;--i)
	{
    
    
		nxt[i]=solve1(d[i]);
		while(top&&st[top]<=d[i])
		{
    
    
			top--;
		}
		st[++top]=d[i];
		pos[top]=i;
	}
	for(int i=1;i<=n;++i)
	{
    
    
		dp[i][0]=nxt[i],sum[i][0]=c[nxt[i]];
	}
	for(int j=1;j<=N;++j)
	{
    
     
		for(int i=1;i<=n;++i)
		{
    
    
			dp[i][j]=dp[dp[i][j-1]][j-1];
			if(dp[i][j])
			{
    
    
				sum[i][j]=sum[i][j-1]+sum[dp[i][j-1]][j-1];
			}
		}
	} 
}
int solve(int x, ll S)
{
    
    
	S-=c[x];
	if(S<=0)
	{
    
    
		return x;
	}
	for(int i=N;i>=0;--i)
		if(dp[x][i]&&S-sum[x][i]>0)
		{
    
    
			S-=sum[x][i];x=dp[x][i];
		}
	return dp[x][0];		//此处返回nxt[x]也可,一样的 
}
int main()
{
    
    
	scanf("%d%d",&n,&Q);
	for(int i=1;i<=n;++i)
	{
    
    
		scanf("%d%d",&d[i],&c[i]);
	}
	init();
	for(int i=1;i<=Q;++i)
	{
    
    
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d\n", solve(x,y));
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_50624971/article/details/113307546