Codeforces Round #424 (Div. 1, rated, based on VK Cup Finals) B. Cards Sorting(树状数组+模拟)

题目链接
在这里插入图片描述
思路:考虑一下每个数被取时候和前一个被取得数之间的贡献,比如12 2 2 10 12 1,很明显10这个是肯定是12取完之后再取10,我们只有知道2和10之间有多少数比10大就行了,如果2的位置在10的右边也很好算,就是总数减去2到10中间的那块就行了,比如2和1,只要总数-【2的位置,1的位置】比2大的数就可以了,可是这里这么算有一个前提,就是你的知道这n个数被取时候的顺序才行,,比如n个数不相同那很好办,比较麻烦的就是相同的数了,这里比方说上面的那个例子,有2个12,那么究竟是那一个12先取呢?很明显就是在12之前取得也就是10的后面依次取,所以是下标为5的12先取,再是下标为1的,这个模拟一次就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(i) (i)&(-i)
const int maxn=1e5+1; 
int c[maxn];
pair<int,int>p[maxn]; 
set<int>s;
vector<int>v[maxn];
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;
}
bool cmp1(const pair<int,int>&a,const pair<int,int>&b)
{
	return a.first==b.first?a.second<b.second:a.first<b.first;
}
bool cmp2(const pair<int,int>&a,const pair<int,int>&b)
{
	return a.first==b.first?a.second>b.second:a.first>b.first;
}
int main()
{
	int n,minn=0,temp=0;
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&p[i].first),p[i].second=i;
	sort(p+1,p+1+n,cmp1);
	for(int i=1;i<=n;++i)
	{
		
		if(p[i].first!=p[i-1].first)
		{
			minn=temp%n;
			temp=0;
		}
		if(p[i].second<minn) p[i].second+=n;
			temp=max(temp,p[i].second);
	}
	sort(p+1,p+1+n,cmp2);
	for(int i=1;i<=n;++i) if(p[i].second>n) p[i].second-=n;
	//for(int i=1;i<=n;++i) cout<<p[i].first<<" "<<p[i].second<<endl;
	ll ans=0;update(p[1].second,1);
	for(int i=2;i<=n;++i)
	{
		if(p[i].second>p[i+1].second)  ans+=query(p[i].second)-query(p[i+1].second);
		else ans+=query(n)-(query(p[i+1].second)-query(p[i].second-1));
		update(p[i].second,1);
	}
	printf("%lld\n",ans+n);
}
发布了391 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

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