[ABC372D] Buildings 题解
很容易发现正着做怎么做都是 的,于是我们想到了 P2947,仔细看会发现它们很像,我们就有了一种想法:反着想,对于每个建筑,从左边一直找出建筑,计数器 ,直到找到更高的建筑,记录下来,那么左边的几个建筑答案就会增加 。
知道了思路就可以思考方法了。从左边一直找出建筑,直到找到更高的建筑可以使用单调栈,区间加 可以用差分,最后做个前缀和即可。
贴个代码:
#include<bits/stdc++.h>
using namespace std;
int n, a[200005], ans[200005], st[200005], head, c[200005];
map<int, int> mp;
int main(){
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i], mp[a[i]] = i;//map是用来方便找出栈顶序号,也可以用 pair
for(int i = 1; i <= n; i ++){
while(head && st[head] < a[i]) ans[i] = ans[i] + ans[mp[st[head --]]] + 1;//答案加栈顶的答案再加上栈顶
st[++ head] = a[i];
}//上面就是普通的单调栈,这是我习惯的写法,比较好理解,其实是一样的
for(int i = 1; i <= n; i ++) ++ ans[i];
for(int i = 1; i <= n; i ++){
c[i - ans[i]] ++;//差分
c[i] --;//差分
}
for(int i = 1; i <= n; i ++) c[i] += c[i - 1];//前缀和求答案
for(int i = 1; i <= n; i ++) cout << c[i] << " ";
return 0;
}
使用 pair
的代码:
#include<bits/stdc++.h>
using namespace std;
int n, a[200005], ans[200005], head, c[200005];
pair<int, int> st[200005];
int main(){
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++){
while(head && st[head].first < a[i]) ans[i] = ans[i] + ans[st[head --].second] + 1;
st[++ head] = {a[i], i};
}
for(int i = 1; i <= n; i ++) ++ ans[i];
for(int i = 1; i <= n; i ++){
c[i - ans[i]] ++;
c[i] --;
}
for(int i = 1; i <= n; i ++) c[i] += c[i - 1];
for(int i = 1; i <= n; i ++) cout << c[i] << " ";
return 0;
}
posted on 2024-09-23 22:02 zhangzirui66 阅读(8) 评论(0) 收藏 举报 来源