Codeforces Round #227 (Div. 2) E. George and Cards(树状数组+贪心+思维)

题目链接
在这里插入图片描述
题意:给一个长度为n的数列,每个数在1-n之间且各不相同。你可以从这个数列中删数:每次选一段区间,可以删除这个区间中最小的那个数,然后每次删除得到的分数是这个区间的长度。题目要你把原序列删成一个规定的长度为k的序列,并要得分最高。
思路:贪心的按数从小到大删,用set来维护b数组,同时二分查找大于当前数的位置,假设当前要删的数是3,那么r就是3的(最远的那个下标),l就是3的前面一个数2的下标+1,具体看代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+1;
#define lowbit(i) (i)&(-i)
ll c[maxn],ans;
int n,k,t,a[maxn],vis[maxn],pos[maxn];
set<int>s;
void update(int x,int v)
{
	while(x<maxn) c[x]+=v,x+=lowbit(x);
 } 
 ll query(int x)
 {
 	ll res=0;
 	while(x>0) res+=c[x],x-=lowbit(x);
 	return res;
 }
int main()
{
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;++i) 
	{
		scanf("%d",&a[i]);
		update(i,1);
		pos[a[i]]=i;
	}
	for(int i=1;i<=k;++i) scanf("%d",&t),vis[t]=1;
	s.insert(0);s.insert(n+1);
	for(int i=1;i<=n;++i)
	{
		if(!vis[i])
		{
			auto it=s.upper_bound(pos[i]);
			int r=(*it)-1,l=*(--it)+1;
			ans+=query(r)-query(l-1);
			update(pos[i],-1);
		}
		else s.insert(pos[i]);
	}
	printf("%lld\n",ans);
}
发布了391 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/105542615