zoukankan      html  css  js  c++  java
  • HDU-3727 Jewel

    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) 

    InputThere 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) 

    OutputOutput 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_1 1 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.

    题解:可持续化线段树的模板题

    AC代码为:


    /*
    有四种操作
    1、在序列最优插入一个数字(该数字从没出现过)
    2、询问序列内某区间第k小值
    3、询问当前序列内数字x是第几小的(x一定在序列中)
    4、询问当前序列内第k小的值
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    using namespace std;
    typedef long long LL;
    const int N = 1e5 + 10;  
    int tot,rt[N]; 
    char s[10];
    vector<int> v;  
    struct data  
    {  
        int id;  
        int l,r,x;  
    }data[N*2];  
       
    inline int getid(int x) {return lower_bound(v.begin(),v.end(),x) - v.begin() + 1;}  
      
    void input(int n)  
    {  
        char s[10];
        int x;  
        for(int i=0;i<n;i++)  
        {  
            scanf("%s",s);  
            if(s[0]=='I')  
            {  
                scanf("%d",&x); 
                data[i].id = 0;  
                data[i].x = x;  
                v.push_back(x);  
            }  
            else if(s[6]=='1')  
            {  
                int a,b,c;  
                scanf("%d%d%d",&a,&b,&c);  
                data[i].id = 1;  
                data[i].l = a, data[i].r = b, data[i].x = c;  
            }  
            else if(s[6]=='2')  
            {  
                scanf("%d",&x);  
                data[i].id = 2;  
                data[i].x = x;  
            }  
            else  
            {  
                scanf("%d",&x);  
                data[i].id = 3;  
                data[i].x = x;  
            }  
        }  
    }    
    struct node  
    {  
        int l,r,sum;  
    }tree[N*24];   
        
    inline void build(int l,int r,int &x) //1~v.size() 
    {  
        x = ++tot;  
        tree[x].sum = 0;  
        if(l==r) return;  
        int m = (l+r) >> 1;  
        build(l,m,tree[x].l);  
        build(m+1,r,tree[x].r);  
    }  
      
    inline void update(int l,int r,int &x,int y,int k)  
    {  
       tree[++tot] = tree[y], tree[tot].sum++,x=tot;  
        if(l==r) return;  
        int m = (l+r) >> 1;  
        if(k<=m) update(l,m,tree[x].l,tree[y].l,k);  
        else update(m+1,r,tree[x].r,tree[y].r,k);  
    }  
      
    inline int query1(int l,int r,int y,int x,int k)  //查找区间第k小的数  
    {  
        if(l==r) return l;  
        int mid = (l+r) >> 1;  
        int sum = tree[tree[x].l].sum - tree[tree[y].l].sum;  
        if(k<=sum) return query1(l,mid,tree[y].l,tree[x].l,k);  
        else return query1(mid+1,r,tree[y].r,tree[x].r,k-sum);  
    }  
      
    inline int query2(int l,int r,int x,int k) //在当前序列中,输出X是第几小的数。  
    {  
        if(l==r) return 1;  
        int mid = (l+r) >> 1;  
        if(k<=mid) return query2(l,mid,tree[x].l,k);  
        else  
        {  
            int sum = tree[tree[x].l].sum;  
            return sum += query2(mid+1,r,tree[x].r,k);  
        }  
    }  
      
    inline int query3(int l,int r,int x,int k) //找到当前序列中第X小的数是几  
    {  
        if(l==r) return l;  
        int mid = (l+r) >> 1;  
        int sum = tree[tree[x].l].sum;  
        if(sum>=k) return query3(l,mid,tree[x].l,k);  
        else return query3(mid+1,r,tree[x].r,k-sum);  
    }      
    int main()  
    {   
        ios::sync_with_stdio(0);  
        cin.tie(0); 
        int n;  
        int cas = 1;  
        while(~scanf("%d",&n))  
        {  
            v.clear();  
            tot = 0;  
            LL ans1 = 0, ans2 = 0, ans3 = 0;  
            input(n);  
            sort(v.begin(),v.end());  
            v.erase(unique(v.begin(),v.end()),v.end());  
            int cnt = v.size();  
            build(1,cnt,rt[0]);  
            int now = 1;  
            for(int i=0;i<n;i++)  
            {  
                if(data[i].id==0)  
                {  
                    update(1,cnt,rt[now],rt[now-1],getid(data[i].x));  
                    now++;  
                }  
                else if(data[i].id==1)  
                {  
                    int l = data[i].l, r = data[i].r, x = data[i].x;  
                    ans1 += v[query1(1,cnt,rt[l-1],rt[r],x)-1];  
                }  
                else if(data[i].id==2) ans2+=query2(1,cnt,rt[now-1],getid(data[i].x));               
                else ans3+=v[query3(1,cnt,rt[now-1],data[i].x)-1];      
            }    
            printf("Case %d: %I64d %I64d %I64d ",cas++,ans1,ans2,ans3);  
        }  
        return 0;  
    }  






  • 相关阅读:
    C#枚举扩展方法,获取枚举值的描述值以及获取一个枚举类下面所有的元素
    C#对IQueryable<T>、IEnumerable<T>的扩展方法
    C#常用处理数据类型转换、数据源转换、数制转换、编码转换相关的扩展
    C#常用8种排序算法实现以及原理简介
    身份证号合法性验证,支持15位和18位身份证号,支持地址编码、出生日期、校验位验证
    C#检验参数合法性公用方法
    MVC中得到成员元数据的Description特性描述信息公用方法
    把对象类型转换成指定的类型帮助类方法
    C#操作图片帮助类
    C#执行Dos命令公用方法
  • 原文地址:https://www.cnblogs.com/csushl/p/9386566.html
Copyright © 2011-2022 走看看