hdu3727 Jewel(划分树)

来源:互联网 发布:2016年淘宝还能刷单吗 编辑:程序博客网 时间:2024/05/16 08:11

Jewel

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1065    Accepted Submission(s): 266


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
10Insert 1Insert 4Insert 2Insert 5Insert 6Query_1 1 5 5Query_1 2 3 2Query_2 4Query_3 3Query_3 1
 

Sample Output
Case 1:1035
Hint
The answers for the 5 queries are 6, 4, 3, 4, 1, respectively.
 

题意:

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

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

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

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

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

题解:Query_1 Query_3划分树可以解决,Query_2用vector+二分。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#define ll long longusing namespace std;const int MAXN = 400010;int tree[20][MAXN];//表示每层每个位置的值int sorted[MAXN];//已经排序好的数int toleft[20][MAXN];//toleft[p][i]表示第i层从1到i有数分入左边vector<int>vec;void build(int l,int r,int dep) {    if(l == r)return;    int mid = (l+r)>>1;    int same = mid - l + 1;//表示等于中间值而且被分入左边的个数    for(int i = l; i <= r; i++) //注意是l,不是one        if(tree[dep][i] < sorted[mid])            same--;    int lpos = l;    int rpos = mid+1;    for(int i = l; i <= r; i++) {        if(tree[dep][i] < sorted[mid])            tree[dep+1][lpos++] = tree[dep][i];        else if(tree[dep][i] == sorted[mid] && same > 0) {            tree[dep+1][lpos++] = tree[dep][i];            same--;        } else            tree[dep+1][rpos++] = tree[dep][i];        toleft[dep][i] = toleft[dep][l-1] + lpos - l;    }    build(l,mid,dep+1);    build(mid+1,r,dep+1);}//查询区间第k大的数,[L,R]是大区间,[l,r]是要查询的小区间int query(int L,int R,int l,int r,int dep,int k) {    if(l == r)return tree[dep][l];    int mid = (L+R)>>1;    int cnt = toleft[dep][r] - toleft[dep][l-1];    if(cnt >= k) {        int newl = L + toleft[dep][l-1] - toleft[dep][L-1];        int newr = newl + cnt - 1;        return query(L,mid,newl,newr,dep+1,k);    } else {        int newr = r + toleft[dep][R] - toleft[dep][r];        int newl = newr - (r-l-cnt);        return query(mid+1,R,newl,newr,dep+1,k-cnt);    }}struct Query {    char s[10];    int l,r,k;} Q[MAXN];int main() {    // freopen("test.in","r",stdin);    int n,m;    int ca=1;    while(~scanf("%d",&m)) {        memset(tree,0,sizeof(tree));        n=0;        for(int i = 0; i < m; i++) {            scanf("%s%d",Q[i].s,&Q[i].l);            if(strcmp(Q[i].s,"Insert")==0) {                tree[0][++n]=Q[i].l;                sorted[n] = tree[0][n];            } else if(strcmp(Q[i].s,"Query_1")==0) {                scanf("%d%d",&Q[i].r,&Q[i].k);            }        }        sort(sorted+1,sorted+n+1);        build(1,n,0);        vec.clear();        ll Q1=0,Q2=0,Q3=0;        int R=0;        for(int i=0; i<m; i++) {            if(Q[i].s[0]=='I') {                R++;                vec.insert(lower_bound(vec.begin(),vec.end(),Q[i].l),Q[i].l);                continue;            }            if(Q[i].s[6]=='1') {                Q1+=query(1,n,Q[i].l,Q[i].r,0,Q[i].k);                continue;            }            if(Q[i].s[6]=='2') {                Q2+=lower_bound(vec.begin(),vec.end(),Q[i].l)-vec.begin()+1;                continue;            }            Q3+=query(1,n,1,R,0,Q[i].l);        }        printf("Case %d:\n%lld\n%lld\n%lld\n",ca++,Q1,Q2,Q3);    }    return 0;}

 

0 0