当前位置: 首页 > news >正文

P14262 [ROI 2015 Day1] 自动好友

题目传送门

我的博客-欢迎光顾

写了一个很另类的容斥。。。比其他dalao的做法复杂不少


(为了方便描述,如果 \(i,j\) 是一对潜在好友,我们就称 \((i,j)\) 是一对朋友对)

(以下的 \(a,b,c\) 均指题目中的三个属性)

首先我们可以枚举两个人并判断它们能否构成一组潜在好友。时间复杂度 \(O(n^2)\)

然后,我们注意到这个题值域很小。于是本人就想着,依次算出 \(a\) 相同而 \(b,c\) 不同的朋友对, \(b\) 相同而 \(a,c\) 不同的朋友对,以及 \(c\) 相同而 \(a,b\) 不同的朋友对。最终答案就是三个朋友对的个数相加(显然不会有重复统计的朋友对)。

求这三种朋友对的方法都差不多。下面我们展开说说如何求 \(a\) 相同而 \(b,c\) 不同的朋友对。(其余同理)

我们可以将原来的人按 \(a\) 属性从小到大排序,这样 \(a\) 相同的人一定是在一个连续区间内的。

如果本题只有两个属性(仍然要求只有一个属性相同),那我们可以考虑记录一下当前 \(a\) 相同的人的左端点编号 \(l\) ,以及一个桶 \(mpb_{i}\) ,记录a属性的值落在这个区间的基础上,b属性为i的人有几个

这样,我们从左往右遍历 \(i\)\(i\) 对答案的贡献就是 \(i-l-mpb_{b_{i}}\)

现在变成三个属性了,怎么办?这个时候容斥就闪亮登场了。

沿用刚才的思路,我们用三个桶,一个桶 \(mpb_{i}\) ,记录a属性的值落在这个区间的基础上,b属性为i的人有几个;一个桶 \(mpc_{j}\) ,记录a属性的值落在这个区间的基础上,c属性为j的人有几个;一个桶 \(mp_{i,j}\) ,记录a属性的值落在这个区间的基础上,b属性为i的人且c属性为j的人有几个

这样, \(i\) 前面 \(a\) 相同但不满足条件的人的数量 \(num\) 就是 \(mpc_{c{i}}+mpb_{b{i}}-mp_{b_{i},c_{i}}\)\(i\) 对答案的贡献就是 \(i-top-num\)

这样我们就能求 \(a\) 相同而 \(b,c\) 不同的朋友对了。同理处理另两种情况即可。

代码实现的时候注意,如果进入了一个新的区间,那么 \(l\) 应当重新赋值,且 你开的几个桶都要初始化为 0 。

\(mp\) 这个桶如果不开 \(a\) 属性的这一位,那每次进入新区间都要初始化,很容易 TLE 。这里我采用了一个空间换时间的策略,给 \(mp\) 数组新开 \(a\) 的一维,这样我们只需要在处理一个大情况前初始化即可。

代码:

P14262正解
#include<bits/stdc++.h>
#define int long long
using namespace std;inline int read(){int x=0,f=1;char c=getchar();while(c<48){if(c=='-') f=-1;c=getchar();}while(c>47) x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f;
}inline void write(int x){if(x<0) putchar('-'),x=-x;if(x<10) putchar(x+'0');else write(x/10),putchar(x%10+'0');
}const int N=1e5+5;
const int M=105;
int n,ans,mp1[M],mp2[M],mp3[M],mp[M][M][M];
//mp1,mp2,mp3:等同于题解中的mpa,mpb,mpc 
struct sw{int b[4];
}a[N];inline bool cmp1(sw x,sw y){return x.b[1]<y.b[1];
}inline bool cmp2(sw x,sw y){return x.b[2]<y.b[2];
}inline bool cmp3(sw x,sw y){return x.b[3]<y.b[3];
}inline void solve(int id){//mp桶的初始化 for(int i=1;i<=100;i++){for(int j=1;j<=100;j++){for(int k=1;k<=100;k++){mp[i][j][k]=0;}}}if(id==1){int top=0;//top:等同于题解中的l sort(a+1,a+n+1,cmp1);for(int i=1;i<=n;i++){int x=a[i].b[1],y=a[i].b[2],z=a[i].b[3];if(a[i].b[id]!=a[i-1].b[id]){//不相同则进入新区间 for(int j=1;j<=100;j++){mp2[j]=mp3[j]=0;}top=i;//记录一下左端点 }else{int x=a[i].b[1],y=a[i].b[2],z=a[i].b[3];//桶题解 int num=mp2[y]+mp3[z]-mp[x][y][z];ans=ans+(i-top-num);}//更新一下桶 mp2[y]++;mp3[z]++;mp[x][y][z]++;}}if(id==2){//注释见上 int top=0;sort(a+1,a+n+1,cmp2);for(int i=1;i<=n;i++){int x=a[i].b[1],y=a[i].b[2],z=a[i].b[3];if(a[i].b[id]!=a[i-1].b[id]){for(int j=1;j<=100;j++){mp1[j]=mp3[j]=0;}top=i;}else{int num=mp1[x]+mp3[z]-mp[x][y][z];ans=ans+(i-top-num);}mp1[x]++;mp3[z]++;mp[x][y][z]++;}}if(id==3){//注释见上 int top=0;sort(a+1,a+n+1,cmp3);for(int i=1;i<=n;i++){int x=a[i].b[1],y=a[i].b[2],z=a[i].b[3];if(a[i].b[id]!=a[i-1].b[id]){for(int j=1;j<=100;j++){mp2[j]=mp1[j]=0;}top=i;}else{int x=a[i].b[1],y=a[i].b[2],z=a[i].b[3];int num=mp2[y]+mp1[x]-mp[x][y][z];ans=ans+(i-top-num);}mp2[y]++;mp1[x]++;mp[x][y][z]++;}}
}signed main(){n=read();for(int i=1;i<=n;i++){a[i].b[1]=read(),a[i].b[2]=read(),a[i].b[3]=read();}solve(1);solve(2);solve(3);printf("%lld",ans);return 0;
}

另,如果你有对拍的需求,也欢迎你用如下代码与你的正解对拍(即 \(O(n^2)\) 代码):

P14262暴力
#include<bits/stdc++.h>
#define int long long
using namespace std;inline int read(){int x=0,f=1;char c=getchar();while(c<48){if(c=='-') f=-1;c=getchar();}while(c>47) x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f;
}inline void write(int x){if(x<0) putchar('-'),x=-x;if(x<10) putchar(x+'0');else write(x/10),putchar(x%10+'0');
}const int N=1e5+5;
int n,a[N],b[N],c[N];signed main(){n=read();for(int i=1;i<=n;i++){a[i]=read(),b[i]=read(),c[i]=read();}int ans=0;for(int i=1;i<=n;i++){for(int j=1;j<i;j++){if((a[i]==a[j]&&b[i]!=b[j]&&c[i]!=c[j])||(a[i]!=a[j]&&b[i]==b[j]&&c[i]!=c[j])||(a[i]!=a[j]&&b[i]!=b[j]&&c[i]==c[j])){ans++;}}}printf("%lld",ans);return 0;
}

如果你觉得这篇题解还不错的话,记得留下你的赞呀qwq

http://www.hskmm.com/?act=detail&tid=35288

相关文章:

  • 软件工程第二次团队作业
  • 超越技术范畴:低代码如何重塑企业数字文化
  • 歌手与模特儿
  • 20251019
  • 十六天
  • 计算机毕业设计 基于EChants的海洋气象数据可视化平台设计与建立 Python 大数据毕业设计 Hadoop毕业设计选题【附源码+文档报告+安装调试】
  • https://www.luogu.com.cn/problem/CF1635E
  • ZR 2025 NOIP 二十连测 Day 5
  • SpringBoot整合Redis教程
  • [VIM] reverse multiple lines in VIM
  • Vue 项目 AI 文档增量更新工具操作手册
  • 4060显卡也能玩转AI改图!Flux.1 Kontext Dev GGUF版本超详细入门教程 - 实践
  • 记账:流水报表
  • 2025年法兰保护罩厂家推荐排行榜,阀门保温罩,法兰罩,法兰防溅罩,法兰保护套,专业防护与定制服务优质供应商
  • 英伟达微型AI工作站的架构解析与性能突破
  • 题解 QOJ 7766 [集训队互测 2023] 栞
  • 遥感的基本概念
  • d435i 标定 imu和相机 用来复现vins_fusion - 教程
  • 20232418 2025-2026-1 《网络与系统攻防技术》实验二实验报告
  • CF1777E Edge Reverse
  • CSP-S 模拟赛 Day 19
  • CSP-S 模拟赛 Day 18
  • 2025年锥芯板品牌口碑排行榜单Top10:行业精选与选择指南
  • 2025年给汤机/重力铸造自动化/机加工自动化厂家推荐榜单:专业设备与智能解决方案权威解析
  • 2025年发电机厂家权威推荐榜:柴油发电机组/康明斯/玉柴/高压/大功率发电机组专业选购指南
  • 强网杯s9初赛 PolyEncryption wp
  • 基于TPS5450DDAR的24V转12V降压电路设计
  • 【STM32项目开源】基于STM32的智能宠物防丢监控便捷的系统
  • 20232409 2025-2026-1 《网络与系统攻防技术》实验三实验报告
  • 训高代