1 条题解

  • 0
    @ 2026-1-28 12:13:19
    #include<bits/stdc++.h>
    using namespace std;
    
    // [1] arr数组-存储同学的身高,输入顺序为「队尾→窗口」(最后一个同学到第一个挨着窗口的同学),最多支持80100个元素
    long long arr[80100];
    
    int main(){
        // [2] n-排队的同学总数(输入的正整数)
    	int n;
    	cin>>n;
        // [3] 读取n个同学的身高,按「队尾→窗口」的顺序存入arr数组
    	for(int i=0;i<n;i++) cin>>arr[i];
    	
        // [4] s-单调递减栈,存储从窗口到当前同学的身高(保证栈内身高递减,栈顶为当前同学前面最近的、身高≥当前同学的人)
    	stack<long long> s;
        // [5] v-辅助栈,存储s中对应身高的同学能看到的人数(与s的元素一一对应,实现复用前面同学的计算结果)
    	stack<long long> v;
        // [6] sum-所有同学能看到的人数之和,类型为long long避免n较大时溢出
    	long long sum=0;
    
        // [7] 逆序遍历(从窗口前的第一个同学,到队尾的同学):因为每个同学的视野仅由「窗口方向(前面)」的同学决定,逆序处理可复用已计算的结果
    	for(int i=n-1;i>=0;i--){
            // [8] 情况1:栈为空(当前是窗口前的第一个同学,前面无同学)
    		if(s.empty()){
    			 s.push(arr[i]);  // 当前同学的身高入栈
    			 v.push(0);       // 前面无同学,能看到0人,入辅助栈
    		}
    		else{
                // [9] count-当前同学能看到的人数,初始化为0
    			int count=0;
                // [10] 维护单调递减栈:弹出所有身高小于当前同学的元素(这些同学都能被当前同学看到)
                // 逻辑:当前同学比这些同学高,因此能看到这些同学,以及这些同学能看到的人数(count += 1 + v.top(),1表示当前弹出的同学,v.top()表示该同学能看到的人数)
    			while(!s.empty() && arr[i]>s.top()){
    				count=count+1+v.top(); 
    				s.pop();
    				v.pop();
    			}
                // [11] 将当前同学的身高和能看到的人数入栈,作为后续同学(队尾方向)的计算依据
    			s.push(arr[i]);
    			v.push(count);
                // [12] 累加当前同学能看到的人数到总结果
    			sum+=v.top();
    		}
    	}
        // [13] 输出所有同学能看到的人数之和
    	cout<<sum;
    	return 0;
    }
    
    • 1

    信息

    ID
    1264
    时间
    1000ms
    内存
    256MiB
    难度
    2
    标签
    递交数
    1
    已通过
    1
    上传者