HDU 5249 离线树状数组求第k大+离散化
Posted 半根毛线code
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5249 离线树状数组求第k大+离散化相关的知识,希望对你有一定的参考价值。
KPI
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1160 Accepted Submission(s): 488
Problem Description
你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度。数十亿的请求被推到一个大管道后同时服务从管头拉取请求。让我们来定义每个请求都有一个重要值。我的KPI是由当前管道内请求的重要值的中间值来计算。现在给你服务记录,有时我想知道当前管道内请求的重要值得中间值。
Input
有大约100组数据。
每组数据第一行有一个n(1≤n≤10000) ,代表服务记录数。
接下来有n行,每一行有3种形式
"in x": 代表重要值为x(0≤x≤109) 的请求被推进管道。
"out": 代表服务拉取了管道头部的请求。
"query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,如果当前管道内有m条请求, 我想知道,升序排序后第floor(m/2)+1th 条请求的重要值.
为了让题目简单,所有的x都不同,并且如果管道内没有值,就不会有"out"和"query"操作。
每组数据第一行有一个n(1≤n≤10000) ,代表服务记录数。
接下来有n行,每一行有3种形式
"in x": 代表重要值为x(0≤x≤109) 的请求被推进管道。
"out": 代表服务拉取了管道头部的请求。
"query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,如果当前管道内有m条请求, 我想知道,升序排序后第floor(m/2)+1th 条请求的重要值.
为了让题目简单,所有的x都不同,并且如果管道内没有值,就不会有"out"和"query"操作。
Output
对于每组数据,先输出一行
Case #i:
然后每一次"query",输出当前管道内重要值的中间值。
Case #i:
然后每一次"query",输出当前管道内重要值的中间值。
Sample Input
6
in 874
query
out
in 24622
in 12194
query
Sample Output
Case #1:
874
24622
Source
题意: 三种操作 ”in x“ 将x 加入到队列
”out“ 删除队头元素
”query“ 队列中现有元素升序排列后 输出第 ( len/2+1) 大元素
题解:1.将所有元素离散化处理 这里的方法比较麻烦 具体看代码有多次映射
2.根据操作 将离散化后的元素加入 树状数组 in~add(x,1),out~add(x,-1);
3.树状数组求第k大
f[n] 树状数组
f[1]=a1
f[2]=a1+a2
f[3]=a3
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<map> 5 #include<algorithm> 6 #include<stack> 7 #include<queue> 8 using namespace std; 9 struct node 10 { 11 int x; 12 int y; 13 } s[10005]; 14 int t; 15 int jishu=0; 16 char a[10005][50]; 17 int b[10005]; 18 int exm; 19 int f[100005]; 20 int coun=0; 21 map<int,int> mp; 22 map<int,int> mpp; 23 queue<int> st; 24 int n; 25 bool cmp(struct node aa,struct node bb ) 26 { 27 return aa.x<bb.x; 28 } 29 void add(int x,int y,int n) 30 { 31 for (;x<=n;x+=x&(-x)) f[x]+=y; 32 } 33 int sum(int x) 34 { 35 int ret=0; 36 for (;x;x-=x&(-x)) ret+=f[x]; 37 return ret; 38 } 39 int find_k(int k) //求第k大 板子 40 { 41 int i,w=0; 42 for (i=20;i>=0;i--) 43 if (w+(1<<i)<=n&&f[w+(1<<i)]<k) 44 { 45 k-=f[w+(1<<i)];w+=1<<i; 46 } 47 return w+1; 48 } 49 int k_num(int k){ 50 int w=0,cnt=0; 51 for(int i=20;i>=0;i--) 52 { 53 54 w+=(1<<i); 55 if(w>n || k<=f[w]) 56 w-=(1<<i); 57 else 58 { 59 k-=f[w]; 60 } 61 } 62 return w+1; 63 } 64 int main() 65 { 66 while(scanf("%d",&t)!=EOF) 67 { jishu++; 68 memset(s,0,sizeof(s)); 69 memset(a,0,sizeof(a)); 70 memset(b,0,sizeof(b)); 71 memset(f,0,sizeof(f)); 72 mp.clear(); 73 mpp.clear(); 74 while(st.size()>0) 75 st.pop(); 76 coun=0; 77 for(int i=1;i<=t;i++) 78 { 79 scanf("%s",&a[i]); 80 if(a[i][0]==‘i‘) 81 { 82 scanf("%d",&exm); 83 s[++coun].x=exm;//存插入的元素 84 s[coun].y=coun;//struct 存储对应位置 85 } 86 } 87 cout<<"Case #"<<jishu<<":"<<endl; 88 sort(s+1,s+1+coun,cmp);//结构体排序 x为主键升序排列 89 b[s[1].y]=1; 90 int k=1; 91 mp[s[1].x]=1; 92 mpp[1]=s[1].x; 93 for(int i=2;i<=coun;i++)//for循环完成离散化处理 94 { 95 if(s[i].x==s[i-1].x) 96 { 97 b[s[i].y]=k; 98 mp[s[i].x]=k;// 与元素的相互映射 99 mpp[k]=s[i].x;// 100 } 101 else 102 { 103 b[s[i].y]=++k; 104 mp[s[i].x]=k; 105 mpp[k]=s[i].x; 106 } 107 } 108 n=k; 109 k=0; 110 for(int i=1;i<=t;i++) 111 { 112 if(a[i][0]==‘i‘) 113 { 114 st.push(mpp[b[++k]]); 115 add(b[k],1,n); 116 } 117 if(a[i][0]==‘o‘) 118 { 119 int now=st.front(); 120 st.pop(); 121 add(mp[now],-1,n); 122 } 123 if(a[i][0]==‘q‘) 124 { 125 int len=st.size(); 126 int location=k_num((len/2)+1); 127 printf("%d\n",mpp[location]); 128 129 } 130 } 131 } 132 return 0; 133 } 134 /* 135 10 136 in 3 137 in 1 138 out 139 in 4 140 query 141 in 2 142 out 143 in 100 144 in 1 145 query 146 */
以上是关于HDU 5249 离线树状数组求第k大+离散化的主要内容,如果未能解决你的问题,请参考以下文章
利用id来进行树状数组,而不是离散化以后的val HDU 4417 离线+树状数组