题目传送门: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\)也可以直接交换。

对于颜色相同,我们把每个可以和当前颜色重量最小的球交换位置的球和当前颜色重量最小的球连一条边。那么对于可以以最小值为媒介交换的球也在一个联通块内了。

对于颜色不同,假设当前球和重量最小的球也颜色不同,那就把当前球和重量最小的那个球连一条边,否则就把当前球与跟重量最小的球颜色不同的球当中重量最小的球连边。如果不存在这个球,那就不连。

然后答案就是:

\[\sum\limits_{i=1}^{m}\frac{cnt_i!}{\prod\limits_{j=1}^{n}sum_j!}
\]

\(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的更多相关文章

  1. AtCoder Grand Contest 012 C:Tautonym Puzzle

    题目传送门:https://agc012.contest.atcoder.jp/tasks/agc012_c 题目翻译 如果一个字符串是好的,那么这个字符串的前半部分和后半部分肯定一模一样.比如\(a ...

  2. AtCoder Grand Contest 012

    AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...

  3. AtCoder Grand Contest 012 A

    A - AtCoder Group Contest Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statem ...

  4. AtCoder Grand Contest 012 A - AtCoder Group Contest(贪心)

    Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement There are 3N participa ...

  5. AtCoder Grand Contest 012 D Colorful Balls

    题意: 有N个球排成一行,第i个球颜色为ci, 权为wi, 如果两个同色球权值和 <= X 则它们可以交换: 如果两个异色球权值和 <= Y 则它们可以交换:不限制交换次数,求能到达的颜色 ...

  6. AtCoder Grand Contest 009 D:Uninity

    题目传送门:https://agc009.contest.atcoder.jp/tasks/agc009_d 题目翻译 定义只有一个点的树权值为\(0\),若干棵(可以是\(0\)棵)权值为\(k\) ...

  7. AtCoder Grand Contest 009 E:Eternal Average

    题目传送门:https://agc009.contest.atcoder.jp/tasks/agc009_e 题目翻译 纸上写了\(N\)个\(1\)和\(M\)个\(0\),你每次可以选择\(k\) ...

  8. AtCoder Grand Contest 004 C:AND Grid

    题目传送门:https://agc004.contest.atcoder.jp/tasks/agc004_c 题目翻译 给你一张网格图,指定的格子是紫色的,要求你构造出两张网格图,其中一张你可以构造一 ...

  9. AtCoder Grand Contest 014 D:Black and White Tree

    题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_d 题目翻译 给你一棵树,每次任选一个点染色,先手染白色,后手染黑色.如果最后存在一个白色的点 ...

随机推荐

  1. phonegap工程搭建基础(一)

      官网:http://cordova.apache.org   一.环境配置 1. 安装Cordova   on OS X and Linux: $ sudo npm install -g cord ...

  2. RecyclerView onItemClick button和布局都有单击事件时的处理方式

    RecyclerView为了给开发人员提供更大的自由度.没有默认的提供onItemClick接口. 网上有一种比較简单的实现方式 , 适用于不须要针对item里面某个button做特殊处理的情况 我眼 ...

  3. C语言-回溯例2

    组合问题 组合:从n个不同元素中取r个不重复的元素组成一个子集,而不考虑其元素的顺序,称为从n个中取r个的无重组合,例如OR = {1,2,3,4}, n = 4, r = 3则无重组合为: {1,2 ...

  4. Java EJB JBoss

    JBoss:JBoss是web服务器的一种,主要做EJB容器,和tomcat集成就可以jsp,servlet,ejb通吃了JBoss有两种版本,一种是独立的,一种是和tomcat集成的,当然都是免费的 ...

  5. 神经网络实现Discuz验证码识别

    最近自己尝试了网上的验证码识别代码项目,该小项目见以下链接: https://cuijiahua.com/blog/2018/01/dl_5.html 数据也就用了作者上传的60000张Discuz验 ...

  6. 服务器启动时Webapp的web.xml中配置的加载顺序(转载)

    一 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Ser ...

  7. new和delete的基本用法

    前言 new和delete是C++中用来动态管理内存分配的运算符,其用法较为灵活.如果你对它们的几种不同用法感到困惑,混淆,那么接着看下去吧. 功能一:动态管理单变量/对象空间 下面例子使用new为单 ...

  8. flume采集微信小程序数据

    flume采集微信小程序数据 flume收集前端埋点数据[1]POST请求http://f.x.com:50000数据格式: JsonArray数据格式示例:[{ "headers" ...

  9. 操作系统 资源管理 zookeeper yarn 进程管理 分布式 yarn诞生背景

    zookeeper 信息保管员 YARN 简介 https://www.ibm.com/developerworks/cn/data/library/bd-yarn-intro/index.html

  10. Mac 操作系统安装 SVN server教程(Subversion With Mac OS X Tutorial)

    Find recent articles on my github page: rubyrobot.github.io © 2006-2014 Imagine Ecommerce Subversion ...