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"操作。

Output

对于每组数据,先输出一行

Case #i:
然后每一次"query",输出当前管道内重要值的中间值。

Sample Input

6
in 874
query
out
in 24622
in 12194
query

Sample Output

Case #1:
874
24622

Source

2015年百度之星程序设计大赛 - 初赛(1)

题意: 三种操作 ”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 */
时间: 2024-12-29 09:02:07

HDU 5249 离线树状数组求第k大+离散化的相关文章

hdu 2985 The k-th Largest Group 树状数组求第K大

The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8353   Accepted: 2712 Description Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to g

POJ2985 The k-th Largest Group[树状数组求第k大值 并查集]

The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8807   Accepted: 2875 Description Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to g

zoj 3635 Cinema in Akiba (树状数组求第K大)

Cinema in Akiba Cinema in Akiba (CIA) is a small but very popular cinema in Akihabara. Every night the cinema is full of people. The layout of CIA is very interesting, as there is only one row so that every audience can enjoy the wonderful movies wit

树状数组求第K大(From CLJ)

int ret=0; for(int p=1<<log2[n];p;p>>=1) if(a[ret+p]<=kth) kth-=a[ret+=p]; return ret;

树状数组求第K小值 (spoj227 Ordering the Soldiers &amp;&amp; hdu2852 KiKi&#39;s K-Number)

题目:http://www.spoj.com/problems/ORDERS/ and http://acm.hdu.edu.cn/showproblem.php?pid=2852 题意:spoj227:告诉每个位置前面有多少个数比当前位置小,求出原序列.hdu2852:设计一个容器,支持几种操作:增加/删除元素,求容器中比a大的数中第k小的数是多少. 分析:两个题思路都是求数组里面的第K小的数.开始一直在找O(N*logN)的方法,后来发现O(N*logN*logN)也是可以过的...两步:和

hdu2852 KiKi&#39;s K-Number 树状数组求第k大数

//再求第k大数时只需要getsum(b-1)<getsum(a)+k<=getsum(b) //b就是a的第k大数 //又gesum(b-1)<=getsum(b)则可以用二分查找来做 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100010; int tree[maxn]; int lowbit(int i) {

区间的关系的计数 HDU 4638 离线+树状数组

题目大意:给你n个人,每个人都有一个id,有m个询问,每次询问一个区间[l,r],问该区间内部有多少的id是连续的(单独的也算是一个) 思路:做了那么多离线+树状数组的题目,感觉这种东西就是一个模板了,23333,反正都是定义右区间的. 这题的关键难度就是如何定义id是连续的呢.我们每次往区间里面放一个数值以后都要add(pos, 1),就是把pos~n的所有的关系都+1.然后如果说在pos之前就出现id-1,就要add(pos[id-1], -1)(同理id+1也是这样),这样子表示从pos[

【转载】【树状数组区间第K大/小】

原帖:http://www.cnblogs.com/zgmf_x20a/archive/2008/11/15/1334109.html 回顾树状数组的定义,注意到有如下两条性质: 一,c[ans]=sum of A[ans-lowbit(ans)+1 ... ans];二,当ans=2^k时, c[ans]=sum of A[1 ... ans]; 下面说明findK(k)如何运作:1,设置边界条件ans,ans'<maxn且cnt<=k:2,初始化cnt=c[ans],其中ans=2^k且k

利用id来进行树状数组,而不是离散化以后的val HDU 4417 离线+树状数组

题目大意:给你一个长度为n的数组,问[L,R]之间<=val的个数 思路:就像标题说的那样就行了.树状数组不一定是离散化以后的区间,而可以是id //看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define m