AtCoder Grand Contest 012 D:Colorful Balls
题目传送门:https://agc012.contest.atcoder.jp/tasks/agc012_d
题目翻译
给你一排一共\(N\)个球,每个球有一个颜色\(c_i\)和一个重量\(w_i\),如果两个球颜色相同,重量相加不超过\(x\)那我就可以交换这俩个球的位置。如果两个球颜色不同,重量相加不超过\(y\)那我也可以交换这俩球的位置。你可以随心所欲的交换或者不交换,求最后颜色序列的种数。\(N\leqslant 2×10^5;c_i\leqslant N;w_i,x,y\leqslant10^9\)
题解
首先,如果\(a,b\)可以交换,\(b,c\)可以交换,那么\(a,c\)也可以直接交换。
对于颜色相同,我们把每个可以和当前颜色重量最小的球交换位置的球和当前颜色重量最小的球连一条边。那么对于可以以最小值为媒介交换的球也在一个联通块内了。
对于颜色不同,假设当前球和重量最小的球也颜色不同,那就把当前球和重量最小的那个球连一条边,否则就把当前球与跟重量最小的球颜色不同的球当中重量最小的球连边。如果不存在这个球,那就不连。
然后答案就是:
\]
\(m\)是联通块个数,\(cnt_i\)表示第\(i\)个联通块大小,\(sum_j\)表示在第\(i\)个联通块中颜色为\(j\)的球有多少个。
时间复杂度:\(O(nlogn)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=2e5+5,pps=1e9+7;
bool vis[maxn];
int n,x,y,tot,ans=1,top;
int fac[maxn],inv[maxn],sta[maxn],insta[maxn];
int sum[maxn],now[maxn],pre[maxn<<2],son[maxn<<2],color[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct Ball {
int c,w,id;
}b[maxn];
int quick(int a,int b) {
int sum=1;
while(b) {
if(b&1)sum=1ll*sum*a%pps;
a=1ll*a*a%pps,b>>=1;
}
return sum;
}
bool cmp1(Ball a,Ball b) {
if(a.c==b.c)return a.w<b.w;
return a.c<b.c;
}
bool cmp2(Ball a,Ball b) {
if(a.w==b.w)return a.c<b.c;
return a.w<b.w;
}
void add(int a,int b) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b;
}
void work1() {
int lst=0;
for(int i=1;i<=n;i++) {
if(b[i].c!=b[lst].c) {
lst=i;continue;
}
if(b[i].w+b[lst].w<=x) {
add(b[i].id,b[lst].id);
add(b[lst].id,b[i].id);
}
}
}
void work2() {
int fake;b[n+1].w=1e9;
for(fake=2;fake<=n;fake++)
if(b[fake].c!=b[1].c)break;
for(int i=2;i<=n;i++)
if(b[i].c!=b[1].c) {
if(b[i].w+b[1].w>y)break;
add(b[i].id,b[1].id);
add(b[1].id,b[i].id);
}
else if(b[i].w+b[fake].w<=y) {
add(b[i].id,b[fake].id);
add(b[fake].id,b[i].id);
}
}
void prepare() {
fac[0]=inv[0]=1;
for(int i=1;i<=n;i++)
fac[i]=1ll*fac[i-1]*i%pps;
inv[n]=quick(fac[n],pps-2);
for(int i=n-1;i;i--)
inv[i]=1ll*inv[i+1]*(i+1)%pps;
}
void dfs(int u) {
vis[u]=1;
int c=color[u];
if(!insta[c]) {
sta[++top]=c;
insta[c]=top;
sum[top]=1;
}
else sum[insta[c]]++;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v])dfs(v);
}
void calc() {
int cnt=0;
while(top) {
ans=1ll*ans*inv[sum[top]]%pps;
cnt+=sum[top],insta[sta[top]]=0,sta[top]=0,sum[top]=0,top--;
}
ans=1ll*ans*fac[cnt]%pps;
}
int main() {
n=read(),x=read(),y=read(),prepare();
for(int i=1;i<=n;i++)
color[i]=b[i].c=read(),b[i].w=read(),b[i].id=i;
sort(b+1,b+n+1,cmp1);work1();
sort(b+1,b+n+1,cmp2);work2();
for(int i=1;i<=n;i++)
if(!vis[i])dfs(i),calc();
printf("%d\n",ans);
return 0;
}
AtCoder Grand Contest 012 D:Colorful Balls的更多相关文章
- AtCoder Grand Contest 012 C:Tautonym Puzzle
题目传送门:https://agc012.contest.atcoder.jp/tasks/agc012_c 题目翻译 如果一个字符串是好的,那么这个字符串的前半部分和后半部分肯定一模一样.比如\(a ...
- AtCoder Grand Contest 012
AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...
- AtCoder Grand Contest 012 A
A - AtCoder Group Contest Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statem ...
- AtCoder Grand Contest 012 A - AtCoder Group Contest(贪心)
Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement There are 3N participa ...
- AtCoder Grand Contest 012 D Colorful Balls
题意: 有N个球排成一行,第i个球颜色为ci, 权为wi, 如果两个同色球权值和 <= X 则它们可以交换: 如果两个异色球权值和 <= Y 则它们可以交换:不限制交换次数,求能到达的颜色 ...
- AtCoder Grand Contest 009 D:Uninity
题目传送门:https://agc009.contest.atcoder.jp/tasks/agc009_d 题目翻译 定义只有一个点的树权值为\(0\),若干棵(可以是\(0\)棵)权值为\(k\) ...
- AtCoder Grand Contest 009 E:Eternal Average
题目传送门:https://agc009.contest.atcoder.jp/tasks/agc009_e 题目翻译 纸上写了\(N\)个\(1\)和\(M\)个\(0\),你每次可以选择\(k\) ...
- AtCoder Grand Contest 004 C:AND Grid
题目传送门:https://agc004.contest.atcoder.jp/tasks/agc004_c 题目翻译 给你一张网格图,指定的格子是紫色的,要求你构造出两张网格图,其中一张你可以构造一 ...
- AtCoder Grand Contest 014 D:Black and White Tree
题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_d 题目翻译 给你一棵树,每次任选一个点染色,先手染白色,后手染黑色.如果最后存在一个白色的点 ...
随机推荐
- 赞一下TMS Software 和 AdvStringGrid
非常久前给Support发Email问能不能在设计期给AdvStringGrid标题加个数字标识.每次我都是自己改代码加上去.这次升级到新版本号,没想到增加了这个功能: 功能虽小可是非常有用,非常多的 ...
- adb命令具体解释(二)——手机缺失sqlite3时操作数据库的多种解决方式
在android应用开发无处不在SQLite数据库的身影.那么在开发中怎么使用adb命令操作数据库的功能呢? 以下我们将完整的介绍与数据库操作相关的命令集及当手机缺少sqlite3的时候的多种解决方式 ...
- vim调试
首先,想调试一个程序的话,输入以下命令: guest-djjtew@ubuntu:~$ python3 -m pdb 1.py 这时候就停止了,等待着你的输入,然后输入"l"的话, ...
- SVG 签名动画 制作
不知道哪天看到的一个朋友圈里面有发的什么什么免费教签名之类的,就看了下SVG,做这功能还不错. 主要用到的几个属性,需要自行百度一下,不详说 stroke-dashoffset , stroke- ...
- Spring的常见问题及答案
目录 Spring 概述 依赖注入 Spring beans Spring注解 Spring数据访问 Spring面向切面编程(AOP) Spring MVC Spring 概述 1. 什么是spri ...
- ecshop购买记录(近期成交数量)显示历史记录
默认只显示最近30天内的销售记录, 按照下面方法修改 就可以显示所有的了 打开 /includes/lib_insert.php 文件 找到下面代码,将之删除即可,一共有两处,都要删除. AND ' ...
- VMware Workstation 14创建mac-10.12虚拟机详细步骤
一.VMware和unlocker的下载和安装 链接:https://pan.baidu.com/s/15Z4DqRENt6JdyfJef_VWSw 密码:40vw 1.安装VMware Works ...
- centos编译 Compiling FFmpeg on CentOS RHEL Fedora
This guide is based on a minimal installation of the latest CentOS release, and will provide a local ...
- windows命令大全(转载)
winver---------检查Windows版本 wmimgmt.msc打开Windows管理体系结构(wmi) wupdmgrWindows更新程序 w脚本Windows脚本宿主设置 write ...
- android日历控件
源码地址 : http://download.csdn.net/detail/abc13939746593/7265459