Loading

【题解】[CCO2020] Exercise Deadlines

考虑依次填入每个位置。

最后一个位置只能填 \(d_i=n\) 的位置,第 \(k\) 个位置只能填 \(d_i\ge k\) 的位置。

我们随着 \(k\) 的减小,决策集合扩大。

那么对于第 \(n\) 个位置,一定选择 \(d_i=n\) 中最大的 \(i\) 。依次类推,第 \(k\) 个位置肯定选择决策集合中最大的数。

需要在线维护加入一个数,查询最大值和删除最大值,直接用优先队列即可。

最后再用树状数组求出逆序对。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 200005
using namespace std;
int n,d[N],c[N];vector<int>u[N];
inline void add(int x){for(;x<=n;x+=x&-x)c[x]++;}
inline int ask(int x){int sum=0;for(;x;x-=x&-x)sum+=c[x];return sum;}
priority_queue<int>q;
int main(){
	scanf("%d",&n);long long ans=0;
	rep(i,1,n)scanf("%d",&d[i]),u[d[i]].push_back(i);
	pre(i,n,1){
		for(int j=0;j<(int)u[i].size();j++)q.push(u[i][j]);
		if(q.empty()){puts("-1");return 0;}
		int cur=q.top();q.pop();
		ans+=ask(cur);add(cur);
	}
	printf("%lld\n",ans);return 0;
}
posted @ 2021-06-07 17:02  7KByte  阅读(61)  评论(0编辑  收藏  举报