zoukankan      html  css  js  c++  java
  • HDU3727

    题目大意

    对一个序列进行以下四种操作:

    1、Insert x 在序列尾部插入x

    2、Query_1 s t k 查询区间[s,t]的第k小

    3、Query_2 x 查询x的在序列中排名

    4、Query_3 k 查询序列中的第k小

    题解

    第一个和第二个显然是主席树能够实现的功能,第三四个操作用vector+lower_bound就可以实现,妈蛋,写完交上去一直WA,fuck,然后把存储操作类型的每个字符串的大小从10改成15居然变RE了!!!才发现用来存储操作的数组开小了,只开到100000。。。改完就A了。。。3687MS,好慢。。。假设插入操作为n,其他操作位m,时间复杂度是nlogn+mlogn 应该没有这么慢的说啊,莫非是lower_bound调用次数太多,所以耗时很多?

    代码:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    #define MAXN 100005
    #define lson l,m,ls[s]
    #define rson m+1,r,rs[s]
    typedef long long LL;
    int ls[20*MAXN],rs[20*MAXN];
    int cnt[20*MAXN],T[MAXN];
    int a[MAXN],num[MAXN];
    char op[2*MAXN][15];
    int L[2*MAXN],R[2*MAXN],K[2*MAXN];
    int tot;
    vector<int>ivec;
    void build(int l,int r,int &s)
    {
        s=++tot;
        cnt[s]=0;
        if(l==r) return;
        int m=(l+r)>>1;
        build(lson);
        build(rson);
    }
    void update(int last,int p,int l,int r,int &s)
    {
        s=++tot;
        ls[s]=ls[last],rs[s]=rs[last];
        cnt[s]=cnt[last]+1;
        if(l==r) return;
        int m=(l+r)>>1;
        if(p<=m) update(ls[last],p,lson);
        else     update(rs[last],p,rson);
    }
    int query(int ss,int tt,int l,int r,int k)
    {
        if(l==r) return r;
        int sum=cnt[ls[tt]]-cnt[ls[ss]];
        int m=(l+r)>>1;
        if(sum>=k) return query(ls[ss],ls[tt],l,m,k);
        else       return query(rs[ss],rs[tt],m+1,r,k-sum);
    }
    int main()
    {
        int m,kase=0;
        while(scanf("%d",&m)!=EOF)
        {
            memset(cnt,0,sizeof(cnt));
            int len=0,n;
            LL qy1=0,qy2=0,qy3=0;
            ivec.clear();
            for(int i=0; i<m; i++)
            {
                scanf("%s%d",op[i],&L[i]);
                if(!strcmp(op[i],"Insert"))
                {
                    ++len;
                    num[len]=a[len]=L[i];
                }
                else if(!strcmp(op[i],"Query_1"))
                    scanf("%d%d",&R[i],&K[i]);
            }
            sort(a+1,a+len+1);
            n=len;
            len=unique(a+1,a+len+1)-a-1;
            for(int i=1; i<=n; i++) num[i]=lower_bound(a+1,a+len+1,num[i])-a;
            tot=0;
            build(1,len,T[0]);
            for(int i=1; i<=n; i++) update(T[i-1],num[i],1,len,T[i]);
            for(int i=0; i<m; i++)
            {
                if(!strcmp(op[i],"Insert"))
                    ivec.insert(lower_bound(ivec.begin(),ivec.end(),L[i]),L[i]);
                else if(!strcmp(op[i],"Query_1"))
                    qy1+=a[query(T[L[i]-1],T[R[i]],1,len,K[i])];
                else if(!strcmp(op[i],"Query_2"))
                    qy2+=lower_bound(ivec.begin(),ivec.end(),L[i])-ivec.begin()+1;
                else
                    qy3+=ivec[L[i]-1];
            }
            printf("Case %d:
    ",++kase);
            printf("%I64d
    %I64d
    %I64d
    ",qy1,qy2,qy3);
        }
        return 0;
    }
  • 相关阅读:
    css3新特性总结
    ES6常用特性总览
    前端第一次面试
    将一个行数在主线程执行的4中方法
    判断邮箱格式和图片压缩
    上传图片的实现
    导航右侧添加按钮、隐藏导航条和状态栏
    从相册选取图片展示并实现自定义事件
    cell添加选中时的背景图片、显示图片和图片自适应框的大小
    设置键盘无色和状态栏风火轮、屏幕截图
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3350699.html
Copyright © 2011-2022 走看看