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 题目翻译 给你一棵树,每次任选一个点染色,先手染白色,后手染黑色.如果最后存在一个白色的点 ...
随机推荐
- 【转】css浮动元素的知识
原文: http://www.cnblogs.com/xuyao100/p/8940958.html ------------------------------------------------- ...
- 纯JS设置首页,增加收藏,获取URL參数,解决中文乱码
雪影工作室版权全部,转载请注明[http://blog.csdn.net/lina791211] 1.前言 纯Javascript 设置首页,增加收藏. 2.设置首页 // 设置为主页 functio ...
- Solaris文件系统管理
不同的操作系统使用不同类型的文件系统 1.文件(管理)系统:是用来对文件和目录进行管理.控制的数据结构的总称. Windows当中的文件系统: ntfs ,fat32 ,fat64 Solaris 当 ...
- java多个文件压缩下载
public static void zipFiles(File[] srcfile,ServletOutputStream sos){ byte[] buf=new byte[1024]; try ...
- 【CODEFORCES】 B. Dreamoon and Sets
B. Dreamoon and Sets time limit per test 1 second memory limit per test 256 megabytes input standard ...
- CentOS Linux搭建独立SVN Server全套流程(转)
环境为centos6.3 1.首先 看看机器上安装了svn了没有 rpm -qa |grep svn 2.如果没有安装 执行 yum -y install subversion 3.安装好了之后 新建 ...
- ubuntu 下的中文输入法的安装和配置- ibus
ibus输入法 Chinese语言包安装 首先需要给Ubuntu16.04安装Chinese语言包支持. 如上图点击其中的Install/Remove Languages…,这个对话框是通过syst ...
- html抽取文本信息-java版(适合lucene建立索引)
import org.htmlparser.NodeFilter; import org.htmlparser.Parser; import org.htmlparser.beans.StringBe ...
- 调试LD_PRELOAD注入的代码
LD_PRELOAD提供了平民化的注入方式固然方便,同一时候也有不便:注入库出错后调试比較困难. 我琢磨了几天找到了可行的调试方法,当然未必是最有效的办法.抛出陋文,希望引来美玉~ 首先.写一段代码作 ...
- GreenPlum 安装方法详解
一.安装环境准备 1.磁盘环境准备 磁盘分区典型配置如下: 文件系统 文件格式 大小 / ext3 50GB,Linux系统的根目录,所有的目录都挂在这个目录下面,建议大小为 ...