LOJ#6432. 「PKUSC2018」真实排名 组合
这题怕不是 sb 题吧,随便分类讨论一下 $i$ 乘不乘 2 倍就没了.
然后细节要注意一下:题中要求的是大于等于.
求值域在 $[L,R]$ 中的元素个数时我用的权值线段树,可能会比二分要慢一点,但是不用判边界.
code:
#include <bits/stdc++.h>
#define ll long long
#define N 100009
#define lson s[x].ls
#define rson s[x].rs
#define inf 2000000000
#define mod 998244353
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int tot;
int a[N],fac[N],inv[N],b[N];
struct data { int sum,ls,rs; }s[N*30];
int qpow(int x,int y)
{
int tmp=1;
for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) tmp=(ll)tmp*x%mod;
return tmp;
}
int INV(int x) { return qpow(x,mod-2); }
void init()
{
fac[0]=inv[0]=1;
for(int i=1;i<N;++i) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=INV(fac[i]);
}
int query(int x,int l,int r,int L,int R)
{
if(!x) return 0;
if(l>=L&&r<=R) return s[x].sum;
int mid=(l+r)>>1,re=0;
if(L<=mid) re+=query(lson,l,mid,L,R);
if(R>mid) re+=query(rson,mid+1,r,L,R);
return re;
}
void update(int &x,int l,int r,int p,int v)
{
if(!x) x=++tot;
s[x].sum+=v;
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) update(lson,l,mid,p,v);
else update(rson,mid+1,r,p,v);
}
int C(int x,int y)
{
if(x<0||y<0||x<y) return 0;
return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int main()
{
// setIO("input");
// freopen("input.out","w",stdout);
int n,k,rt=0,x,y,z;
init();
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i) scanf("%d",&a[i]),update(rt,0,inf,a[i],1),b[i]=a[i];
for(int i=1;i<=n;++i)
{
if(a[i]==0) printf("%d\n",C(n,k));
else
{
x=(a[i]&1)?a[i]/2:(a[i]/2)-1;
int SUM=query(rt,0,inf,0,x)+query(rt,0,inf,a[i],inf)-1;
int ANS=C(SUM,k);
update(rt,0,inf,a[i],-1);
int sum2=query(rt,0,inf,a[i],inf);
int sum1=query(rt,0,inf,2*a[i],inf);
// 还缺 sum2-sum1
int to=query(rt,0,inf,a[i],2*a[i]-1);
(ANS+=C(to,sum2-sum1)*C(n-to-1,k-sum2+sum1-1)%mod)%=mod;
printf("%d\n",ANS);
update(rt,0,inf,a[i],1);
}
}
return 0;
}

浙公网安备 33010602011771号