QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#617318 | #9310. Permutation Counting 4 | Lautisticyc | TL | 0ms | 0kb | C++14 | 2.4kb | 2024-10-06 14:54:18 | 2024-10-06 14:54:19 |
answer
/*
首先获得神谕用容斥。
就可以只看上限。
那么大的必然包含小的区间。
用上我们的结论,如果大的选到小的区间里,就可以把他们交换,从而得到另一个符合要求的序列,那么这个%2就可以消掉。
那么对于一个选好的上限序列,我们只需要排序后计算prod?{1~n}(x[i]-x[i-1])
也就是选择的序列必须相隔都是奇数才可以计入。
因为%2,所以容斥时+1-1没区别。
现在还是算不了啊
如果我们同时选择了l-1和r会怎么样呢?
并不会怎么样。
?
对于原来就选择了l-1的方案,如果加上r,那么如果插在奇数中间,必定出现偶数。不会计算。
如果插在最后并是奇数距离,那么就计算了一次。
等一会儿。
一共n个,n的距离,必须每个都是距离1才行啊。
也就是每一个选择l-1,r中的一个,最后覆盖1~n的方案数。
那么如果l-1=0,必选r,不连边
否则将l-1和r连一条边。
如果必选有重复就直接返回0
统计每个连通块里是否只有一个必选。
如果>1就0,如果==0就看siz奇偶.
如果有环,就0.
*/
#include<bits/stdc++.h>
using namespace std;
int t,n,l,r,ans,edg[1000010],siz[1000010],fa[1000010],bx[1000010];
bool bix[1000010];
void read(int &hhh)
{
int x=0;
char c=getchar();
while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^'0');
c=getchar();
}
hhh=x;
}
int findfa(int x)
{
if(fa[x]==x) return x;
return fa[x]=findfa(fa[x]);
}
int main()
{
freopen("sample.in","r",stdin);
read(t);
while(t--)
{
read(n);
ans=1;
for(int i=1;i<=n;++i)
{
fa[i]=i;
bix[i]=0;
bx[i]=0;
siz[i]=1;
edg[i]=0;
}
for(int i=1;i<=n;++i)
{
read(l);
read(r);
if(l==1)
{
if(bix[r]) ans=0;
bix[r]=1;
++bx[findfa(r)];
}
else
{
int u=findfa(l-1),v=findfa(r);
if(u!=v)
{
fa[u]=v;
siz[v]+=siz[u];
bx[v]+=bx[u];
edg[v]+=edg[u]+1;
}
else ++edg[v];
}
}
for(int i=1;i<=n;++i)
{
if(findfa(i)==i)
{
// printf(" %d %d %d %d\n",bx[i],siz[i],edg[i],i);
if(bx[i]>1) ans=0;
else if(bx[i]==1)
{
if(siz[i]<=edg[i]) ans=0;
}
else
{
if(siz[i]!=edg[i]) ans=0;
}
}
}
printf("%d\n",ans);
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Time Limit Exceeded
input:
4 5 1 2 1 5 1 2 1 2 2 2 5 1 1 2 4 2 3 5 5 3 4 5 3 5 1 2 3 4 3 5 3 3 5 1 5 1 4 4 5 5 5 1 2