zoukankan      html  css  js  c++  java
  • 倍增或线段树,给出一个数,让它模一连串的数

                       J   Shopping

    链接:http://codeforces.com/gym/101201 

    题意:

    给出一系列商品的价格,下面再给出q个人浏览商品的起点到末尾,和他带上的钱,如果看到能买的商品就买最多个,输出每个人浏览后所剩余的钱

    分析:

    如果对于每个人都遍历一遍的话,最坏的情况超过了1e9。

    由于是取模运算,可以找到这个数列的第一个比他小的数,模它,比它大则无视。一个数最多模lgn下。

    接下来最重要的是找到第一个比V小的数的位置

    用倍增的方法存储一段数的最小值。

    然后再以lgn的速度求出从a开始,比v小的第一个数。

    ac代码1:倍增

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=200000+10;
    #define LL long long
    LL num[maxn];
    LL Min[maxn][25];//Min[i][j]从第i个元素到i+2ej-1个元素的最小值
    int fin(LL V,int s)
    {
        for(int i=20;i>=1;i--)
        {
            while(Min[s][i]<=V&&Min[s][i-1]>V)
            {
                s+=(1<<(i-1));
            }
        }
        if(num[s]<=V)
           return s;
        else
           return maxn;
    }
    int main()
    {
        int n,q,s,o;
        LL V;
        cin>>n>>q;
        for(int i=1;i<=n;i++)
        {
            scanf("%I64d",&num[i]);
            Min[i][0]=num[i];
        }
        for(int j=1;j<=20;j++)//建立倍增数组
        for(int i=1;i<=n;i++)
        {
            if(i+(1<<(j-1))<=n)
                Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
            else
                Min[i][j]=Min[i][j-1];
        }
        for(int i=1;i<=q;i++)
        {
            scanf("%I64d %d %d",&V,&s,&o);
            int k=fin(V,s);
            while(k<=o)
            {
                V%=num[k];
                k=fin(V,k+1);
            }
            printf("%I64d
    ",V);
        }
        return 0;
    }
    View Code

     ac代码2 :线段树

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 const int maxn=200000+10;
     5 struct Node
     6 {
     7     LL Min;
     8     int s,o;
     9 }node[maxn*4];
    10 LL num[maxn];
    11 void build(int s,int o,int xt)
    12 {
    13     node[xt].s=s,node[xt].o=o;
    14     int mid=(s+o)/2;
    15     if(s==o)
    16     {
    17         node[xt].Min=num[s];
    18         return ;
    19     }
    20     build(s,mid,xt*2);
    21     build(mid+1,o,xt*2+1);
    22     node[xt].Min=min(node[xt*2].Min,node[xt*2+1].Min);
    23 }
    24 int getnext(LL V,int ss ,int n)
    25 {
    26     if(ss>n)return 0;
    27     int xt=1;
    28     while(node[xt].s!=ss)
    29     {
    30         if(ss<=(node[xt].o+node[xt].s)/2)
    31             xt*=2;
    32         else xt=2*xt+1;
    33     }
    34     if(node[xt].Min<=V)
    35     {
    36         while(node[xt].o!=node[xt].s)
    37         {
    38             if(node[xt*2].Min<=V)
    39                 xt=2*xt;
    40             else
    41                 xt=2*xt+1;
    42         }
    43         return node[xt].o;
    44     }
    45     else return getnext(V,node[xt].o+1,n);
    46 }
    47 int main()
    48 {
    49     int n,q,a,b;
    50     LL V;
    51     cin>>n>>q;
    52     for(int i=1;i<=n;i++)
    53        scanf("%I64d",&num[i]);
    54     build(1,n,1);
    55     for(int i=1;i<=q;i++)
    56     {
    57          scanf("%I64d %d %d",&V,&a,&b);
    58          int next=getnext(V,a,n);
    59          while(next<=b&&next)
    60          {
    61              V%=num[next];
    62              next=getnext(V,next+1,n);
    63          }
    64          printf("%I64d
    ",V);
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    .NET自动化测试手记(2) 实例:点击计算器按钮
    解决httpwebrequest无法通过使用代理的局域网获取response的问题
    iOS开发之SQLite
    iOS开发之AVAudioPlayer 音频播放
    iOS开发 键盘添加工具条(toolbar)
    UIPickerView中的实例方法
    TextField
    UISearchBar和UISearchDisplayController
    Objectivec 字符串遍历的几种方法
    《Write ObjectiveC Code》学习笔记
  • 原文地址:https://www.cnblogs.com/carcar/p/8918767.html
Copyright © 2011-2022 走看看