A. Printing charges (thinking + bisection + minimum suffix/st/line segment tree)

Idea: First find a recent price less than or equal to the current paper price, and then find a way to quickly count the minimum value of the subsequent prices.

I feel that this question has been written in cf.

To find the location, due to the monotonicity, two points can be used. Pay attention to the position where the two points cannot be found.

The smaller the recommended constant is the minimum maintenance suffix of the mind.

Contribute to my pool of code: maintain the minimum suffix O(1) query and compare.

 


Talk about other methods, maintain the minimum value of a sequence and query, you can st table or line segment tree, try st table. But the dichotomy stuck the boundary. (Let's change the bipartite article)

It turns out that wa was sent 8 times: l=n+1 when it was not found; although the boundary was taken, l--, the st boundary pos=l+1 I took was still 0; resulting in wa. Sure enough, the way of thinking is less error-prone

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+1000;
typedef long long LL;
inline LL read()
{
	LL x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
LL n,m;
LL a[maxn],s[maxn],q[maxn];
LL f[maxn][40];
int main(void)
{
  	LL n,m;n=read();m=read();
  	///for(LL i=0;i<=n+10;i++) s[i]=1e18;
	for(int i=1;i<=n;i++) {
        s[i]=read();
        q[i]=read();
        a[i]=s[i]*q[i];
	}
	LL t=log(n)/log(2)+1;
	for(int i=1;i<=n;i++) f[i][0]=a[i];
	for(int j=1;j<t;j++)
		for(int i=1;i<=n-(1<<j)+1;i++)
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    while(m--){
        LL x;x=read();
        if(n==1){
            printf("%lld\n",x*q[1]);
            continue;
        }
       /// LL l=lower_bound(s+1,s+1+n,x)-s;
        LL l=upper_bound(s+1,s+1+n,x)-s-1;
        LL res=x*q[l];
        if(l==0) res=1e18;
        LL pos=l+1;
        if(pos<=n){
            LL k=log(n-pos+1)/log(2);
            LL ans2=min(f[pos][k],f[n-(1<<k)+1][k]);
            printf("%lld\n",min(ans2,res));
        }
		else printf("%lld\n",res);
    ///    debug(ans2);
    ///    debug(res);
       /// LL ans2=q[l]*x;
       /// debug(ans1);debug(ans2);

    }
return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/112912464