【题解】[COCI2020-2021#1] Tenis

solution:

恶心题。考点:位运算 + 模拟。

我们将比赛分成两类:第一种是严格的胜利,即赢家的获胜位置严格小于输家的获胜位置。第二种是非严格的胜利,这意味着球员在球场上的获胜位置是相等的。

现在问题转化为在一个 3 列的网格上统计。提供 k c z n o l kcznol kcznol 大佬的 O ( n ) O(n) O(n) 算法,暴踩标算:

  1. 从左往右扫一遍,对于这一列的每个球员是第一次出现,那么我们统计 ( i + 1 , n ) (i+1,n) (i+1,n) 的答案;否则直接跳过。具体我们要维护 c n t [ 8 ] [ 3 ] cnt[8][3] cnt[8][3] 表示在状态 m a s k mask mask 的第 i i i 行排的最小且球场编号最小的球员的位置。
  2. 现在我们计算非严格胜利。枚举 i i i , i 2 i2 i2 ( i < i 2 ) (i<i2) (i<i2) , 如果 x x x, y y y 都不等于 0 0 0 ( x ≠ y ) (x\ne y) (x=y), 我们可以枚举 i 3 ∈ [ 0 , 2 ] i3\in [0,2] i3[0,2] , 使得在输家位置最靠前的情况下场地编号最小,就可以比较出 x x x , y y y 的结果。

常数大概有 2 3 ∗ 3 ∗ 3 = 72 2^3*3*3=72 2333=72

#include <bits/stdc++.h> #define ll long long #define INF 0x3f3f3f3f #define PII pair<int,int> using namespace std; const int mx=1e5+5; int n,a[3][mx],id[mx][3],cnt[8][3],ans[mx]; ll ans2[3]; int in[mx]; //转化为一个三行的表格,然后求啥 ? inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x; } void add(int j,int w) { for(int s=1;s<=7;s++) { int mn_i=-1; for(int i=0;i<=2;i++) { if(s>>i&1&&(mn_i==-1||id[j][i]<id[j][mn_i])) mn_i=i; } cnt[s][mn_i]+=w; } } signed main() { // freopen("data.in","r",stdin); n=read(); for(int i=0;i<=2;i++) { for(int j=1;j<=n;j++) { id[a[i][j]=read()][i]=j; } } for(int j=1;j<=n;j++) add(j,1); for(int j=1;j<=n;j++) { for(int i=0;i<=2;i++) { if(in[a[i][j]]) a[i][j]=0; //player a[i][j] 已经计算过了 else { add(a[i][j],-1); for(int i1=i;i1<=2;i1++) { //in[x] : 状压 if(a[i1][j]==a[i][j]) { in[a[i][j]]|=1<<i1; } } } } for(int i=0;i<=2;i++) { if(a[i][j]) { int x=a[i][j]; //cnt[i][j] 记录 状态为 i 的当中最优决策为 j 的 player 个数 for(int t=0;t<=2;t++) { ans2[t]+=cnt[in[x]][t]; ans[x]+=cnt[in[x]][t]; } for(int i1=i+1;i1<=2;i1++) { //对于非严格的处理(我们首先比较败者名次靠前,再比较场地编号) if(a[i1][j]) { int y=a[i1][j]; PII mn={n+1,n+1}; for(int t=0;t<=2;t++) { //此处 x 取得最优,当前得到的点对为 (id[y][t], t) if(id[x][t]==j) { mn=min(mn,{id[y][t],t}); } //此处 y 取得最优,当前得到的点对为 (id[x][t], t) if(id[y][t]==j) { mn=min(mn,{id[x][t],t}); } } //得到所举办的场地 ans2[mn.second]++; ans[id[x][mn.second]==j?x:y]++; } } } } } printf("%lld %lld %lld\n",ans2[0],ans2[1],ans2[2]); for(int i=1;i<=n;i++) printf("%d ",ans[i]); }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530284.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(8)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示