2022.3.28#关于维护区间排序第k的值
2022-03-28

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 }

浙公网安备 33010602011771号