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;
}