2022.3.28#关于维护区间排序第k的值

2022-03-28

SP15376 RMID - Running Median

 

1.权值线段树

常用的方法,但是写起来比较繁琐且容易出错。

  1 #include<iostream>
  2 #include<vector>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<unordered_map>
  6 using namespace std;
  7 #define maxn 100010
  8 int tree[maxn<<2];
  9 vector<int>a,b;
 10 int len;
 11 unordered_map<int,int>umap;
 12 inline int read()
 13 {
 14     int x=0,f=1;char ch=getchar();
 15     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
 16     while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
 17     return x*f;
 18 }
 19 int cmp(int a,int b)
 20 {
 21     return a<b;
 22 }
 23 void pushup(int root)
 24 {
 25     tree[root]=tree[root*2]+tree[root*2+1];
 26 }
 27 void build(int l,int r,int root)
 28 {
 29     int mid=l+(r-l)/2;
 30     tree[root]=0;
 31     if(l<r)
 32     {
 33         build(l,mid,root*2);
 34         build(mid+1,r,root*2+1);
 35     }
 36 }
 37 void update(int x,int l,int r,int root)
 38 {
 39     int mid=l+(r-l)/2;
 40     tree[root]++;
 41     if(l<r)
 42     {
 43         if(x<=mid)
 44         update(x,l,mid,root*2);
 45         else
 46         update(x,mid+1,r,root*2+1);
 47     }
 48 }
 49 void delet(int x,int l,int r,int root)
 50 {
 51     int mid=l+(r-l)/2;
 52     if(tree[root]>0)
 53     tree[root]--;
 54     if(l<r)
 55     {
 56         if(x<=mid)
 57         delet(x,l,mid,root*2);
 58         else
 59         delet(x,mid+1,r,root*2+1);
 60     }
 61 }
 62 int query(int k,int l,int r,int root)
 63 {
 64     if(l>=r)
 65     return l;
 66     int mid=l+(r-l)/2;
 67     if(k<=tree[root*2])
 68     return query(k,l,mid,root*2);
 69     else
 70     return query(k-tree[root*2],mid+1,r,root*2+1);
 71 }
 72 int main(void)
 73 {
 74     int t;
 75     cin>>t;
 76     while(t--)
 77     {
 78         int num;
 79         num=read();
 80         while(num!=0)
 81         {
 82             a.push_back(num);
 83             num=read();
 84         }
 85         for(int i=0;i<a.size();i++)
 86         if(a[i]!=-1)
 87         b.push_back(a[i]);
 88         sort(b.begin(),b.end(),cmp);
 89         len=unique(b.begin(),b.end())-b.begin();
 90         int cnt=0;
 91         for(int i=0;i<b.size();i++)
 92         if(umap[b[i]]==0)
 93         umap[b[i]]=++cnt;
 94         build(1,len,1);
 95         cnt=0;
 96         for(int i=0;i<a.size();i++)
 97         {
 98             if(a[i]!=-1)
 99             {
100                 cnt++;
101                 update(umap[a[i]],1,len,1);
102             }
103             else
104             {
105                 int midd=(cnt+1)/2;//中位数的取法
106                 int res=query(midd,1,len,1);
107                 printf("%d\n",b[res-1]);
108                 delet(umap[b[res-1]],1,len,1);
109                 cnt--;
110             }
111         }
112     }
113     return 0;
114 }

2.对顶堆

利用大根堆和小根堆,大根堆维护小于等于k的,小根堆维护大于k的,对于第k值可以o1查询,删除,变k,维护,都是O(logn)

 1 //对顶堆使用一个大根堆,一个小根堆维护排序后第k个数。
 2 //支持维护,插入,删除,k值+-1,O(logn)
 3 //查询,O(1).
 4 #include<iostream>
 5 #include<queue>
 6 using namespace std;
 7 int main(void)
 8 {
 9     int n;
10     cin>>n;
11     while(n--)
12     {
13         priority_queue<int,vector<int>,less<int> >a;
14         priority_queue<int,vector<int>,greater<int> >b;
15         int opt;
16         cin>>opt;
17         while(opt!=0)
18         {
19             if(opt==-1)
20             {
21                 printf("%d\n",a.top());
22                 a.pop();
23             }
24             else
25             {
26             if(a.empty()||opt<=a.top())
27             a.push(opt);
28             else
29             b.push(opt);
30             }
31             int mid=(a.size()+b.size()+1)/2;
32             if(a.size()>mid)
33             {
34                 b.push(a.top());
35                 a.pop();
36             }
37             else if(a.size()<mid)
38             {
39                 a.push(b.top());
40                 b.pop();
41             }
42             cin>>opt;
43         }
44     }
45     return 0;
46 }

 

posted @ 2022-03-28 16:30  Tiachi  阅读(61)  评论(0)    收藏  举报