【千里码】商品数量1,2(哈希,线段树)

  • 当在天猫购物,使用关键词搜索商品时,可以选择很多附选条件,比如品牌,价格等,之后会出现符合当前条件的商品及数量,如图,搜索词为:羽绒服,附选条件为:价格¥500-¥1000
  • 主页陈列出符合条件的商品,以及一个商品数量(见右上角),但商品数量会因为商家上架、下架商品而改变,因此买家在不同时间段搜索商品时,显示的数量会不一样。
  • 接下来包含一个含有多行的文本文件,文件的每行代表上架,下架,查询三种行为的一种,本题默认查询对象是‘衣服’。
  • 请计算所有买家查询结果的总和。
    • 举例: 一个拥有6行的文件。
      • up 3 11 (有一个商家上架了3件11rmb的衣服。)
      • query 11 25 (有一个买家查询11rmb-25rmb的衣服的数量。这里的查询结果是:3件)
      • up 5 25 (有一个商家上架了5件25rmb的衣服。)
      • query 11 25 (有一个买家查询11rmb-25rmb的衣服的数量。这里的查询结果是:8件)
      • down 3 25 (有一个商家下架了3件25rmb的衣服。)
      • query 20 25 (有一个买家查询20rmb-25rmb的衣服的数量。这里的查询结果是:2件)

    • 这题的答案是所有买家查询结果的总和为13(3+8+2=13)。
    题目2:
    • 本题与‘商品数量-1’题型一致,仅改变文本文件。
    • 请下载本题文本文件,计算所有买家查询结果的总和。


  • 题目2就是加大了数量,不过下面代码都是可以计算出来的。
  • #include <iostream>
    #include <cstdio>
    #include<ctime>
    using namespace std;
    int num[111111];
    int main()
    {
        freopen("f:/demo//144043063958496.txt","r",stdin);
        char s[8];
        clock_t start,finish;
        start=clock();
        int t1,t2;
        long long ans=0;
        while(scanf("%s%d%d",s,&t1,&t2)!=EOF){
            if(s[0]=='u'){
                num[t2]+=t1;
            }else if(s[0]=='d'){
                num[t2]-=t1;
            }else{
                for(int i=t1;i<=t2;i++)
                    ans+=num[i];
            }
        }
        finish=clock();
        printf("%lld\n",ans);
        cout << finish-start   << "/" << CLOCKS_PER_SEC  << " (s) "<< endl;
        return 0;
    }
    

    我还特别加了个时间函数看它跑十万的数据需要多久,运行结果如下:

3.7秒,在ACM题中肯定是超时的,于是我就用线段树来做了一遍。

  • #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<ctime>
    #include<iostream>
    using namespace std;
    typedef struct{
    int left,right;
    int val;
    } node;
    node tree[100001*4];
    void build (int node,int left,int right)
    {
        tree[node].left=left;
        tree[node].right=right;
        tree[node].val=0;
        if(left==right) return ;
        int  mid=(left+right)>>1;
        build(node*2,left,mid);
        build(node*2+1,mid+1,right);
    }
    
    void update(int node,int pos,int val)
    {
        if(tree[node].left==pos&&tree[node].right==pos){
            tree[node].val+=val;
            return;
        }
        int mid=(tree[node].left+tree[node].right)>>1;
        if(pos<=mid)
            update(node*2,pos,val);
        else if(pos>mid)
            update(node*2+1,pos,val);
        tree[node].val=tree[node*2].val+tree[node*2+1].val;
    }
    
    
    int query(int node,int left,int right)
    {
    
        if (tree[node].left == left &&  tree[node].right == right)
        return tree[node].val;
        if (tree[node].left > right ||  tree[node].right < left)
        return 0;
        int mid;
        mid=(tree[node].left + tree[node].right)>>1;
        if (right <= mid)
        return query(node * 2, left, right) ;
        else if (mid < left)
        return query(node * 2 + 1, left, right) ;
        else
        return query(node * 2, left, mid)+query(node * 2 + 1, mid + 1, right) ;
    }
    
    int main()
    {
        freopen("f:/demo//144043063958496.txt","r",stdin);
        char s[8];
        clock_t start,finish;
        start=clock();
        int t1,t2;
        long long ans=0;
        int n=100000;
        build(1,1,n);
        while(scanf("%s%d%d",s,&t1,&t2)!=EOF){
            if(s[0]=='u'){
                update(1,t2,t1);
            }else if(s[0]=='d'){
                update(1,t2,-t1);
            }else{
               ans+=query(1,t1,t2);
            }
        }
        finish=clock();
        printf("%lld\n",ans);
        cout << finish-start   << "/" << CLOCKS_PER_SEC  << " (s) "<< endl;
        return 0;
    }
    
    可以看到速度的巨大的提升:

  • 看到这个结果时,真的感觉莫名的开心啊,这就是算法的乐趣所在吧.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值