P7166

代码较为简短清晰的一种实现


题意

给出三种场地中排第几的是哪个人(如样例一的最后一行表示第 \(3\) 个人排第一),并且给出两人之间决定在哪里打的方式。求最终的比赛情况。

思路

对于一般的情况,两个人在三个场地的排名各不相同,那么决定的因素就是两人的最小排名是多少。据此,我们可以按每个人的最小排名排序。

观察一个排序后的数组,我们根据每个人的最小排名,把数组分成数个连续段,同一段的最小排名相等。根据题意,这个段的大小至多为 \(3\)

对于不同的段 \(i\),它总是可以确定这个段后面的每一个人与它比赛的情况,那么一般的情况就可以很方便的处理了。

而对于可能出现的相同最小值,根据题意,我们需要知道另一个人的具体排名。在 \(i\) 时暴力枚举后面的所有人显然是不现实的。转换一下,记录 \(i\) 前面不能确定的相同最小值的个数,把值相等的那些场地状压,同时分别记录对应的个数。每到一个新的人,就去解决前面遗留的问题。

对于段内,由于数量较少,可以直接暴力判断。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,cnt[N];
ll ans[5],pre[10];
struct per{
	int ka,kb,kc,id;
}a[N]; 
struct node{
	int x,y,id;
}tmp[5];
inline bool cmp(node xx,node yy){//模拟题目给出的排序规则 
	if(min(xx.x,xx.y)==min(yy.x,yy.y)) return max(xx.x,xx.y)==max(yy.x,yy.y)?xx.id<yy.id:max(xx.x,xx.y)<max(yy.x,yy.y);
	return min(xx.x,xx.y)<min(yy.x,yy.y);
}
inline bool mcp(per x,per y){
	return min(x.ka,min(x.kb,x.kc))<min(y.ka,min(y.kb,y.kc));
}
int main(){
	scanf("%d",&n);
	int t;
	for(int i=1;i<=n;++i) scanf("%d",&t),a[t].ka=i;
	for(int i=1;i<=n;++i) scanf("%d",&t),a[t].kb=i;
	for(int i=1;i<=n;++i) scanf("%d",&t),a[t].kc=i,a[t].id=t;//含糊的题意 
	sort(a+1,a+1+n,mcp);
	for(int l=1,r,num;l<=n;){
		r=l,num=min(a[r].ka,min(a[r].kb,a[r].kc));
		while(r<=n&&min(a[r].ka,min(a[r].kb,a[r].kc))==num) ++r;//找段 
		for(int i=l;i<r;++i){//处理前面遗留问题 
			for(int j=1;j<8;++j){//001~111
				int mn=1e9,id=0;
				if((j&1)&&a[i].ka<mn) mn=a[i].ka,id=0;
				if((j&2)&&a[i].kb<mn) mn=a[i].kb,id=1;
				if((j&4)&&a[i].kc<mn) mn=a[i].kc,id=2;
				ans[id]+=pre[j];
			}
		}
		for(int i=l;i<r;++i){
			cnt[a[i].id]+=n-r+1;//打赢后面的 
			int st=0;
			if(a[i].ka==num) st|=1;
			if(a[i].kb==num) st|=2;
			if(a[i].kc==num) st|=4;
			++pre[st];
			for(int j=i+1;j<r;++j){//暴力判断 
				tmp[0]={a[i].ka,a[j].ka,0};
				tmp[1]={a[i].kb,a[j].kb,1};
				tmp[2]={a[i].kc,a[j].kc,2};
				sort(tmp,tmp+3,cmp);
				if(tmp[0].x<tmp[0].y) ++cnt[a[i].id];
				else ++cnt[a[j].id];
				++ans[tmp[0].id];
			}
		}
		l=r;
	}
	printf("%lld %lld %lld\n",ans[0],ans[1],ans[2]);
	for(int i=1;i<=n;++i) printf("%d ",cnt[i]);
	return 0;
}

记得开 longlong。

posted @ 2023-11-12 13:11  mRXxy0o0  阅读(22)  评论(0)    收藏  举报