HDU3727--Jewel (主席树 静态区间第k大)

Jewel

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

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_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

貌似很水的一道题,,主席树裸题,不知道为什么现场就几个队了这个题。。对于查询某个数的排名,我是用树状数组搞的。。和主席树没有联系

注意HDU上的题目有一点问题,,不是231  而是2的31次方

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 typedef long long ll;
  7 const int maxn = 2e5+100;
  8 int lson[maxn*20],rson[20*maxn],c[maxn*20];
  9 int tree[maxn],tot,idx,maxv;
 10 int build (int l,int r)
 11 {
 12     int root = tot++;
 13     c[root] = 0;
 14     if (l != r)
 15     {
 16         int mid =(l + r) >> 1;
 17         lson[root] = build(l,mid);
 18         rson[root] = build(mid+1,r);
 19     }
 20     return root;
 21 }
 22 int update(int root,int pos,int val)
 23 {
 24     int newroot = tot++;
 25     int tmp = newroot;
 26     int l = 1,r = maxv;
 27     c[newroot] = c[root] + val;
 28     while (l < r)
 29     {
 30         int mid = (l + r) >> 1;
 31         if (pos <= mid)
 32         {
 33             rson[newroot] = rson[root];
 34             root = lson[root];
 35             lson[newroot] = tot++;
 36             newroot = lson[newroot];
 37             r = mid;
 38         }
 39         else
 40         {
 41             lson[newroot] = lson[root];
 42             root = rson[root];
 43             rson[newroot] = tot++;
 44             newroot = rson[newroot];
 45             l = mid + 1;
 46         }
 47         c[newroot] = c[root] + val;
 48     }
 49     return tmp;
 50 }
 51 int query(int left,int right,int k)
 52 {
 53     int l_root = tree[left-1];
 54     int r_root = tree[right];
 55     int l = 1, r = maxv;
 56     while (l < r)
 57     {
 58         int mid = (l + r) >> 1;
 59         if (c[lson[r_root]] - c[lson[l_root]] >= k)
 60         {
 61             r = mid;
 62             l_root = lson[l_root];
 63             r_root = lson[r_root];
 64         }
 65         else
 66         {
 67             l = mid + 1;
 68             k -=  c[lson[r_root]] - c[lson[l_root]];
 69             l_root = rson[l_root];
 70             r_root = rson[r_root];
 71         }
 72     }
 73     return l;
 74 }
 75 int query(int root,int l,int r,int k)
 76 {
 77     if (l == r)
 78         return l;
 79     int mid = (l + r) >> 1;
 80     if (k <= mid)
 81         return query(lson[root],l,mid,k);
 82     else
 83         return c[lson[root]] + query(rson[root],mid+1,r,k);
 84 }
 85 ll bit_arr[maxn];
 86 inline int lowbit (int x)
 87 {
 88     return x & -x;
 89 }
 90 void ADD(int x)
 91 {
 92     while (x < maxn)
 93     {
 94         bit_arr[x]++;
 95         x += lowbit (x);
 96     }
 97 }
 98 ll get_sum(int x)
 99 {
100     ll res = 0;
101     while (x)
102     {
103         res += bit_arr[x];
104         x -= lowbit (x);
105     }
106     return res;
107 }
108 struct
109 {
110     int x,y,k,flag;
111 }Q[maxn];
112 ll vec[maxn];
113 int main(void)
114 {
115     #ifndef ONLINE_JUDGE
116         freopen("in.txt","r",stdin);
117     #endif // ONLINE_JUDGE
118     int n,cas = 1;
119     while (~scanf ("%d",&n))
120     {
121         memset(bit_arr,0,sizeof(bit_arr));
122         printf("Case %d:\n",cas++);
123         tot = idx = 0;
124         for (int i = 0; i < n; i++)
125         {
126             char op[15];
127             scanf ("%s",op);
128             if (strcmp(op,"Insert") == 0)
129             {
130                 int x;
131                 scanf ("%d",&x);
132                 Q[i].flag = 0;
133                 Q[i].x = x;
134                 vec[idx++] = x;
135             }
136             if (strcmp(op,"Query_1") == 0)
137             {
138                 int u,v,k;
139                 scanf ("%d%d%d",&u,&v,&k);
140                 Q[i].flag = 1;
141                 Q[i].x = u,Q[i].y = v,Q[i].k = k;
142             }
143             if (strcmp(op,"Query_2") == 0)
144             {
145                 int x;
146                 scanf ("%d",&x);
147                 Q[i].flag = 2;
148                 Q[i].x = x;
149             }
150             if (strcmp(op,"Query_3") == 0)
151             {
152                 int k;
153                 scanf ("%d",&k);
154                 Q[i].flag = 3;
155                 Q[i].x = k;
156             }
157         }
158         sort(vec,vec+idx);
159         idx = unique(vec,vec+idx) - vec;
160         maxv = idx ;
161         tree[0] = build(1,maxv);
162         int now = 1;
163         ll ans1 = 0, ans2 = 0, ans3 = 0;
164         for (int i = 0; i < n; i++)
165         {
166             if (Q[i].flag == 0)
167             {
168                 int tmp = lower_bound(vec,vec+idx,Q[i].x) - vec + 1;
169                 tree[now] = update(tree[now-1],tmp,1);
170                 ADD(tmp);
171                 now++;
172             }
173             if (Q[i].flag == 1)
174             {
175                 ans1 += vec[query(Q[i].x,Q[i].y,Q[i].k)-1];
176             }
177             if (Q[i].flag == 2)
178             {
179                 int tmp = lower_bound(vec,vec+idx,Q[i].x) - vec + 1;
180                 ans2 += get_sum(tmp);
181             }
182             if (Q[i].flag == 3)
183             {
184                 ans3 += vec[query(1,now-1,Q[i].x)-1];
185             }
186         }
187         printf("%I64d\n%I64d\n%I64d\n",ans1,ans2,ans3);
188     }
189     return 0;
190 }
时间: 2024-10-16 14:01:40

HDU3727--Jewel (主席树 静态区间第k大)的相关文章

POJ2104-- K-th Number(主席树静态区间第k大)

[转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段树,每个节点记录这个区间所包含的元素个数,建树和查询时的区间范围用递归参数传递,然后用二叉查找树的询问方式即可:即如果左边元素个数sum>=K,递归查找左子树第K大,否则递归查找右子树第K – sum大,直到返回叶子的值. 现在我们要回答对于区间[l, r]的第K大询问.如果我们能够得到一个插入原序

[poj 2104]主席树+静态区间第k大

题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即可得到第k大(小)元素. #include<cstdio> #include<vector> #include<algorithm> using namespace std; #define lson(i) node[i].lson #define rson(i) node

洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)

题目链接 //离散化后范围1~cnt不要错 #include<cstdio> #include<cctype> #include<algorithm> //#define gc() getchar() #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=2e5+5,MAXIN=2e6; int n,m,A[N],ref[N],cn

poj2761静态区间第k大

例题:poj2761 题目要求:给定一个长度为n的序列,给定m个询问,每次询问求[l,r]区间内的第k大: 对于这道题目来说,很多算法都可以使用,比如说树套树(一个负责划分区间,一个负责维护这段区间内的信息),主席树等: 对这道题我使用的是主席树: 主席树对付区间第k大是很优秀的,代码短,而且常数小: 主席树的主要功能是,建立n颗范围是1-i的权值线段树,对两颗线段树做差,就可以任意一个区间内的权值线段树: 详细看代码: #include<iostream> #include<cstdi

主席树(静态区间第k大)

前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建一棵新的线段树,用来记录出现每个数字出现了多少次的前缀和. 那么假设要求区间[l,r]的第k大,将第r棵线段树减去第l-1棵线段树,像上面求所有数的第k大一样来求就可以了. 但是,对于每一个数都建一个线段树显然会爆空间. 现在考虑如何节约空间. 假设现在有四个数1 4 2 3,依次加入,可以这样处理

hdu 2665 可持久化线段树求区间第K大值(函数式线段树||主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=2665 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The first line is the number of the test cases. For each test case, the first line contain two integer n and m (

HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2那个. 思路: 主席树操作,这里的思路是从n到1开始建树.其他就是主席树查询区间第K小,计算区间不同值个数. #include <algorithm> #include <iterator> #include <iostream> #include <cstring&

HDU3473--Minimum Sum(静态区间第k大)

Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3047    Accepted Submission(s): 701 Problem Description You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you

poj 2401 划分树 求区间第k大的数

题目:http://poj.org/problem?id=2104 划分树待我好好理解下再写个教程吧,觉得网上的内容一般,,, 模板题: 贴代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define CLR(a) memset(a,0,sizeof(a)) const int MAXN = 1000