• HDU3727 Jewel(主席树+树状数组(或二分))


    Problem Description

    Jimmy wants to make a special necklace for his girlfriend. He bought many beads with various sizes, and no two beads are with the same size. Jimmy can't remember all the details about the beads, for the necklace is so long. So he turns to you for help.

    Initially, there is no bead at all, that is, there is an empty chain. Jimmy always sticks the new bead to the right of the chain, to make the chain longer and longer. We number the leftmost bead as Position 1, and the bead to its right as Position 2, and so on. Jimmy usually asks questions about the beads' positions, size ranks and actual sizes. Specifically speaking, there are 4 kinds of operations you should process:

    Insert x 
    Put a bead with size x to the right of the chain (0 < x < 231, and x is different from all the sizes of beads currently in the chain)
    Query_1 s t k 
    Query the k-th smallest bead between position s and t, inclusive. You can assume 1 <= s <= t <= L, (L is the length of the current chain), and 1 <= k <= min (100, t-s+1)
    Query_2 x
    Query the rank of the bead with size x, if we sort all the current beads by ascent order of sizes. The result should between 1 and L (L is the length of the current chain)
    Query_3 k
    Query the size of the k-th smallest bead currently (1 <= k <= L, L is the length of the current chain)

     

    Input

    There are several test cases in the input. The first line for each test case is an integer N, indicating the number of operations. Then N lines follow, each line contains one operation, as described above. 

    You can assume the amount of "Insert" operation is no more than 100000, and the amounts of "Query_1", "Query_2" and "Query_3" are all less than 35000.
    There are several test cases in the input. The first line for each test case is an integer N, indicating the number of operations. Then N lines follow, each line contains one operation, as described above. 

    You can assume the amount of "Insert" operation is no more than 100000, and the amounts of "Query_1", "Query_2" and "Query_3" are all less than 35000.Query the rank of the bead with size x, if we sort all the current beads by ascent order of sizes. The result should between 1 and L (L is the length of the current chain)
    Query_3 k
    Query the size of the k-th smallest bead currently (1 <= k <= L, L is the length of the current chain)

     

    Output

    Output 4 lines for each test case. The first line is "Case T:", where T is the id of the case. The next 3 lines indicate the sum of results for Query_1, Query_2 and Query_3, respectively. 

     

    Sample Input

    10
    Insert 1
    Insert 4
    Insert 2
    Insert 5
    Insert 6
    Query_11 5 5
    Query_1 2 3 2
    Query_2 4
    Query_3 3
    Query_3 1
     

    Sample Output

    Case 1:
    10
    3
    5

    Hint

    The answers for the 5 queries are 6, 4, 3, 4, 1, respectively.

    题意:

    输入n,再输入n个操作,操作有四种 

     0,  Insert X:插入x到序列末尾 
     1,  query_1 L R X:在当前序列中的[l,r]区间找第x小的数。 
     2,  query_2 X:在当前序列中,输出X是第几小的数。 
     3,  query_3 X:找到当前序列中第X小的数是几。 
    然后输出的是3种query的和。

    思路:

    操作1和操作3是查询区间第k小,主席树。

    操作2是求排名,用树状数组或者二分。

    在线转化为离线。

     求Kth的主席树的模板见我之前写的:http://www.cnblogs.com/hua-dong/p/7931778.html

    操作2为二分的代码:

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<map> 
    using namespace std;
    const int maxn=200010;
    int a[maxn],b[maxn],Innum,n;//a是位置,b是值。Innum是输入的个数,即 
    int cnt,ql,qr,Case=0; 
    long long sum1,sum2,sum3;
    struct questions
    {
        int opt;//0,1,2,3
        int x,y,k;
    }Qst[maxn<<1];
    struct PLTree
    {
        int ch[maxn * 20][2],sum[maxn * 20],rt[maxn];
        void build(int& now,int l,int r)
        {
            now = ++ cnt;
            sum[now] = 0;
            if(l == r) return ;
            int Mid = (l + r)>>1;
            build(ch[now][0],l,Mid);
            build(ch[now][1],Mid + 1,r);
        }
        void insert(int& now,int last,int l,int r,int pos)
        {
            now = ++ cnt;
            ch[now][0]=ch[last][0];
            ch[now][1]=ch[last][1];
            sum[now] = sum[last] + 1;
            if(l == r) return ; 
            int Mid = (l+r) >> 1;
            if(pos <= Mid) insert(ch[now][0],ch[last][0],l,Mid,pos);
            else insert(ch[now][1],ch[last][1],Mid + 1,r,pos);
        }
        int query(int ss,int tt,int l,int r,int k)
        {
             if(l == r) return l;
             int Mid =(l + r) >> 1,tmp = sum[ch[tt][0]] - sum[ch[ss][0]];
             if(k <= tmp) return query(ch[ss][0],ch[tt][0],l,Mid,k);
             else return query(ch[ss][1],ch[tt][1],Mid + 1,r,k - tmp);
        }
    };
    PLTree P;
    void _init()
    {
        Innum=cnt=0;
        sum1=sum2=sum3=0;
    }
    void _scanf()
    {
        char chr[10];
        for(int i=1;i<=n;i++){
            scanf("%s",chr);
            if(chr[0]=='I'){
                Qst[i].opt=0;
                scanf("%d",&Qst[i].x);
                a[++Innum]=Qst[i].x;
                b[Innum]=a[Innum];
            }
            else {   
                Qst[i].opt=chr[6]-'0';
                if(chr[6]=='1')   scanf("%d%d%d",&Qst[i].x,&Qst[i].y,&Qst[i].k);
                else   scanf("%d",&Qst[i].k);
            }
        }
    }
    void _disp()
    {
        sort(b+1,b+Innum+1);
        for(int i=1;i<=Innum;i++)
          a[i]=lower_bound(b+1,b+Innum+1,a[i])-b;
    }
    void _work()
    {
        P.build(P.rt[0],1,Innum);
        int nowcnt=0,ans;
        for(int i=1;i<=n;i++){
            if(Qst[i].opt==0) {
                nowcnt++;
                P.insert(P.rt[nowcnt],P.rt[nowcnt-1],1,Innum,a[nowcnt]); 
            }
            else if(Qst[i].opt==1){
                ans=P.query(P.rt[Qst[i].x-1],P.rt[Qst[i].y],1,Innum,Qst[i].k);
                sum1+=b[ans];
            }
            else if(Qst[i].opt==2){
                int L=1,R=nowcnt;
                while(L<=R){
                    int Mid=(L+R)>>1;
                    ans=P.query(P.rt[0],P.rt[nowcnt],1,Innum,Mid);
                    if(b[ans]==Qst[i].k) {
                       sum2+=Mid;
                       break;
                    }
                    else if(b[ans]<Qst[i].k) L=Mid+1;
                    else R=Mid-1;
                }   
            }
            else {
                ans=P.query(P.rt[0],P.rt[nowcnt],1,Innum,Qst[i].k);
                sum3+=b[ans];
            }
        }
        printf("Case %d:
    ",++Case);
        printf("%lld
    %lld
    %lld
    ",sum1,sum2,sum3);
    }
    int main()
    {
        while(~scanf("%d",&n)){        
            _init();
            _scanf();//输入 
            _disp();//离散
            _work();
        }
        return 0;
    }

    操作2为树状数组的代码:

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<map> 
    using namespace std;
    const int maxn=200010;
    int a[maxn],b[maxn],Innum,n;//a是位置,b是值。Innum是操作为输入的个数,即 
    int cnt,ql,qr,Case=0; 
    long long  sum1,sum2,sum3;
    int c[maxn<<1];
    int lowbit(int x )
    {
        return x&-x;
    }
    void add( int x )
    {
        while(x < Innum){
            c[x]++;
            x += lowbit ( x );
        }
    }
    int sum(int x )
    {
        int ret = 0;
        while (x){
            ret += c[x];
            x -= lowbit ( x );
        }
        return ret;
    }
    struct questions
    {
        int opt;//0,1,2,3
        int x,y,k;
    }Qst[maxn<<1];
    struct PLTree
    {
        int ch[maxn * 20][2],sum[maxn * 20],rt[maxn];
        void build(int& now,int l,int r)
        {
            now = ++ cnt;
            sum[now] = 0;
            if(l == r) return ;
            int Mid = (l + r)>>1;
            build(ch[now][0],l,Mid);
            build(ch[now][1],Mid + 1,r);
        }
        void insert(int& now,int last,int l,int r,int pos)
        {
            now = ++ cnt;
            ch[now][0]=ch[last][0]; 
            ch[now][1]=ch[last][1];
            sum[now] = sum[last] + 1;
            if(l == r) return ; 
            int Mid = (l+r) >> 1;
            if(pos <= Mid) insert(ch[now][0],ch[last][0],l,Mid,pos);
            else insert(ch[now][1],ch[last][1],Mid + 1,r,pos);
        }
        int query(int ss,int tt,int l,int r,int k)
        {
             if(l == r) return l;
             int Mid =(l + r) >> 1,tmp = sum[ch[tt][0]] - sum[ch[ss][0]];
             if(k <= tmp) return query(ch[ss][0],ch[tt][0],l,Mid,k);
             else return query(ch[ss][1],ch[tt][1],Mid + 1,r,k - tmp);
        }
    };
    PLTree P;
    void _init()
    {
        Innum=cnt=0;
        sum1=sum2=sum3=0;
        memset(c,0,sizeof(c));
    }
    void _scanf()
    {
        char chr[10];
        for(int i=1;i<=n;i++){
            scanf("%s",chr);
            if(chr[0]=='I'){
                Qst[i].opt=0;
                scanf("%d",&Qst[i].x);
                a[++Innum]=Qst[i].x;
                b[Innum]=a[Innum];
            }
            else {   
                Qst[i].opt=chr[6]-'0';
                if(chr[6]=='1')   scanf("%d%d%d",&Qst[i].x,&Qst[i].y,&Qst[i].k);
                else   scanf("%d",&Qst[i].k);
            }
        }
    }
    void _disp()
    {
        sort(b+1,b+Innum+1);
        for(int i=1;i<=Innum;i++)
          a[i]=lower_bound(b+1,b+Innum+1,a[i])-b;
    }
    void _work()
    {
        P.build(P.rt[0],1,Innum);
        int nowcnt=0,ans;
        for(int i=1;i<=n;i++){
            if(Qst[i].opt==0) {
                nowcnt++;
                P.insert(P.rt[nowcnt],P.rt[nowcnt-1],1,Innum,a[nowcnt]); 
                add(a[nowcnt]);
            }
            else if(Qst[i].opt==1){
                ans=P.query(P.rt[Qst[i].x-1],P.rt[Qst[i].y],1,Innum,Qst[i].k);
                sum1+=b[ans];
            }
            else if(Qst[i].opt==2){
                int tmp=sum(lower_bound(b+1,b+Innum+1,Qst[i].k)-b);
                sum2+=tmp;
            }
            else {
                ans=P.query(P.rt[0],P.rt[nowcnt],1,Innum,Qst[i].k);
                sum3+=b[ans];
            }
        }
        printf("Case %d:
    ",++Case);
        printf("%lld
    %lld
    %lld
    ",sum1,sum2,sum3);
    }
    int main()
    {
        while(~scanf("%d",&n)){        
            _init();
            _scanf();//输入 
            _disp();//离散
            _work();
        }
        return 0;
    }
  • 相关阅读:
    osc搜索引擎框架search-framework,TngouDB,gso,
    当Scheduler拿不到url的 时候,不能立即退出
    摘要算法CRC8、CRC16、CRC32,MD2 、MD4、MD5,SHA1、SHA256、SHA384、SHA512,RIPEMD、PANAMA、TIGER、ADLER32
    sha256
    非对称加密RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。使用最广泛的是RSA算法
    3个著名加密算法(MD5、RSA、DES)的解析
    DOM
    面向对象
    抽象工厂在ADO.Net中的应用
    Provider Pattern提供者模式和策略模式
  • 原文地址:https://www.cnblogs.com/hua-dong/p/7954258.html
Copyright © 2020-2023  润新知