ZOJ 3726 RMQ + 二分法

本文提供ZOJ 3726题目的解决方案,介绍使用RMQ预处理最小值查询来解决购买纸张的问题。通过二进制求幂方法计算区间长度,实现快速查询区间最小值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5072

区域赛真干的话题

通过率最高的一个问题 不到一半认为这OK  然后WA果断地 另外int无用long long WA

好久没用RMQ 调试也花了一点时间,

upper——bound返回的是大于x的第一个数的下标,最大当然是返回end的位置,注意推断下

注意一点,如果须要打印的张数为x              s[i]=<x<s[i+1]   事实上 要找的是ans=min(p[i]*x,s[i+1]*p[i+1],s[i+1]*p[i+2]...s[n]*p[n]),所以单单二分必定不行啊


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
#include <cmath>

using namespace std;

const int MAXN = 1e5+100;
#define IN(s) freopen(s,"r",stdin)
#define ll long long
#define ull unsigned long long
const ll INF = ((ull)(-1))>>1;
ll s[MAXN],p[MAXN],tot[MAXN];
int n,m;
ll d[20];
ll st[MAXN][20];
void init()
{
    for(int i=0;i<n;i++)st[i][0]=tot[i+1];
    int k = (int)( log(double(n*1.0)/log(2.0)) ) +1;
    for(int j=1;j<k;j++)
        for(int i=0;i<n;i++)
        {
            if(i + d[j-1]-1 <n)
            {
                st[i][j] = min( st[i][j-1], st[i+d[j-1]][j-1] );
            }
            else break;
        }
}

void query(int q)
{
    int y=n-1;
    for(int i=0;i<q;i++)
    {
        int x,k;
        scanf("%d",&x);
        int id= upper_bound(s+1,s+1+n,x)-(s+1);
        if(id>=n)
        {
            printf("%lld\n",p[n]*x);
            continue;
        }
        ll ans=INF;
        ans=min(ans,p[id]*x);
        k=int( log(double(y-id+1)/log(2.0)) );
        ans=min(ans,min(st[id][k],st[y-d[k]+1][k]));
        printf("%lld\n",ans);
    }
}

int main()
{
    //IN("zoj3726.txt");
    d[0]=1;
    for(int i=1;i<21;i++)d[i]=2*d[i-1];
    int ncase;
    scanf("%d",&ncase);
    while(ncase--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld",&s[i],&p[i]);
            tot[i]=s[i]*p[i];
        }
        init();
        query(m);
    }
    return 0;
}


版权声明:本文博客原创文章。博客,未经同意,不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值