zoukankan      html  css  js  c++  java
  • ZOJ 3726 RMQ + 二分法

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


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

  • 相关阅读:
    C++范围解析运算符::的使用
    C程序的内存布局
    ARM中LDR伪指令与LDR加载指令
    每天一个linux命令(12):more命令
    C++ explicit关键字
    C++内联函数详解
    C++友元详解
    C++ new操作符详解
    CDN技术详解笔记
    字符串匹配(KMP 算法 含代码)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4674640.html
Copyright © 2011-2022 走看看