中位数优先容器

要求编写一个容器,它可支持两种操作:push()和pop(),push(K)操作可将元素K放入容器,pop()操作可将容器中的中位值弹出。

例如:push(1),push(2),push(3)后pop()[输出为2]。

解决方法,创建一个最大值优先的优先队列,将其记为左队列ql,创建一个最小值优先的优先队列,将其记为右队列qr,

我们规定ql不为空时,ql.top()为中位值,记为mid,对于push(k),如果k>mid,则将k压入右边优先队列qr,如果k<=mid怎将其压入

左边优先队列ql,然后将左右两个队列做平衡处理。pop()则只需将ql.top()的值弹出后做平衡处理即可。这种方法和快排算法中将

一个序列分成大于mid的和小于等于mid的两部分的做法相似。

题目链接:http://acm.hdu.edu.cn/diy/contest_showproblem.php?cid=16719&pid=1005

代码:

#include<cstdio>
#include<vector>
#include<queue>

using namespace std;

struct cmp1  
{    
    bool operator ()(int &a,int &b)  
    {    
        return a>b;//最小值优先     
    }    
};    

struct cmp2  
{    
    bool operator ()(int &a,int &b)  
    {    
        return a<b;//最大值优先     
    }    
}; 

priority_queue<int,vector<int>,cmp1>qr;//最小值优先     
priority_queue<int,vector<int>,cmp2>ql;//最大值优先
int ls,rs;

void balance(void)
{
     int idx=(ls+rs+1)/2;
     while(ls<idx)
     {
          int k=qr.top();
          ql.push(k);
          qr.pop();
          ls++;
          rs--;
     }
     while(ls>idx)
     {
          int k=ql.top();
          qr.push(k);
          ql.pop();
          ls--;
          rs++;
     }
     
}

void push(int k)
{
     if(ls==0) {
          ql.push(k);
          ls++;
          return ;
     }
     int mid=ql.top();
     if(k>mid) qr.push(k),rs++;
     else ql.push(k),ls++;
     balance();
}

void pop(void)
{
     if(ls<=0) {
          printf("No Element!\n");
          return ;
     }
     int ans=ql.top();
     ql.pop();
     ls--;
     balance();
     printf("%d\n",ans);
}

int main()
{
    int n;
    while(scanf("%d", &n)!=EOF){
          ls=rs=0;
          qr=priority_queue<int,vector<int>,cmp1>();
          ql=priority_queue<int,vector<int>,cmp2>();
          for(int i=0;i<n;i++) {
                int c,k;
                scanf("%d",&c);
                if(c==0) {
                     scanf("%d",&k);
                     //printf("push %d\n",k);
                     push(k);
                }
                else pop();
                //printf("ls=%d rs=%d\n",ls,rs);
          }
          printf("\n");
    }
    return 0;
}


<think>好的,用户现在想知道怎么用C++中的auto来遍历二维数组。首先,我得回想一下C++中的范围for循环和auto关键字的使用方法。范围for循环在C++11引入,可以方便地遍历容器,而auto可以自动推导变量类型,简化代码。 用户提到的二维数组可能指的是不同的数据结构,比如原生数组、vector的vector,或者数组的数组。每种结构的遍历方式可能略有不同,我需要分别考虑。 首先,原生二维数组的情况。例如,int arr[3][4]。这时候使用auto遍历的话,外层循环的每个元素是一个一维数组。但原生数组在范围for循环中会退化为指针,所以可能需要使用引用来避免指针问题。这时候,正确的写法应该是用auto &row来遍历每一行,然后内层循环用auto element遍历每个元素。 接下来是vector的vector,比如vector<vector<int>> vec。这时候每一行是一个vector<int>,所以外层循环可以用auto &row来获取每一行的引用,避免拷贝。内层循环同样用auto &element来遍历每个元素,特别是当元素是复杂对象时,使用引用可以提高效率。 然后,用户可能在使用过程中遇到问题,比如在原生二维数组中使用auto row会导致row成为指针,这时候内层循环无法用范围for遍历,因为指针没有begin和end方法。这时候需要解释正确的做法,或者建议使用vector代替原生数组。 另外,还要考虑是否需要修改元素。如果只是读取,可以使用const auto &,如果需要修改,则用auto &。这会影响代码的正确性和效率。 还要注意多维数组的维度问题,比如动态分配的数组或者不规则二维数组(每行长度不同)。这时候需要确保内层循环正确遍历每个子数组的元素。 可能用户在使用过程中遇到编译错误,比如类型不匹配,或者试图用auto直接遍历指针,这时候需要指出正确的类型推导和使用引用的必要性。 最后,总结各种情况的示例代码,帮助用户理解不同数据结构下的遍历方法,并提醒注意事项,如避免拷贝、正确使用引用、处理动态数组等。</think>在C++中遍历二维数组使用`auto`关键字时,需根据数组类型选择不同遍历方式。以下是三种典型场景的解决方案: --- ### 一、原生二维数组(固定尺寸) ```cpp int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}; // 正确遍历方式 for(auto &row : arr) { // 必须使用引用避免数组退化为指针 for(auto &element : row) { // 使用引用避免拷贝 cout << element << " "; } cout << endl; } ``` --- ### 二、vector构成的二维数组 ```cpp vector<vector<int>> vec = {{1,2}, {3,4,5}, {6}}; // 标准遍历方式 for(const auto &row : vec) { // 使用const引用避免拷贝子vector for(auto num : row) { // 值拷贝适用于基础类型 cout << num << " "; } cout << endl; } // 带修改的遍历 for(auto &row : vec) { // 非const引用可修改子vector for(auto &num : row) { // 引用可修改元素值 num *= 2; } } ``` --- ### 三、动态分配的二维数组(指针形式) ```cpp int **dynamicArr = new int*[3]; for(int i=0; i<3; ++i) dynamicArr[i] = new int[4]{i*4+1, i*4+2, i*4+3, i*4+4}; // 遍历方法(需已知维度) for(int i=0; i<3; ++i) { for(auto *ptr = dynamicArr[i]; ptr != dynamicArr[i]+4; ++ptr) { cout << *ptr << " "; } cout << endl; } ``` --- ### 关键对比表 | 数组类型 | 外层循环`auto`类型 | 内存管理要求 | 代码示例特点 | |------------------|--------------------|-----------------------|----------------------------------| | 原生二维数组 | `auto &` | 自动管理 | 必须使用引用防止退化为指针 | | vector二维数组 | `const auto &` | RAII自动管理 | 灵活处理不规则二维结构 | | 动态分配指针数组 | `auto *` | 需手动`delete[]` | 需配合传统循环控制边界 | --- ### 常见错误及解决方案 1. **指针退化问题** ```cpp // 错误写法 for(auto row : arr) { // row退化为int* for(auto num : row) { // 编译错误:指针没有begin()/end() // ... } } ``` 2. **非常量引用绑定临时值** ```cpp // 危险写法 for(auto &row : vector<vector<int>>{{1,2},{3}}) { // 临时对象不能绑定非const引用(C++11后允许延长生命周期) } ``` --- ### 最佳实践建议 1. 优先使用`vector<vector<T>>`代替原生数组 2. 只读访问时使用`const auto &`组合 3. 需要修改元素时使用`auto &` 4. 动态分配数组建议封装为智能指针 ```cpp // 使用unique_ptr的二维数组 auto smartArr = make_unique<unique_ptr<int[]>[]>(3); for(int i=0; i<3; ++i) smartArr[i] = make_unique<int[]>(4); for(int i=0; i<3; ++i) { for(auto &num : span(smartArr[i].get(), 4)) { cout << num << " "; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值