loj6432「PKUSC2018」真实排名(线段树+组合数学)

分i有没有被选讨论一下就好了qaq
写了个线段树果然垫底了qaq

#include 
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define mod 998244353
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,K,a[N],inv[N],fac[N],rt=0,owo=0,nn=1e9;
struct node{
    int sum,lc,rc;
}tr[N*30];
inline void ins(int &p,int l,int r,int x){
    if(!p) p=++owo;tr[p].sum++;if(l==r) return;int mid=l+r>>1;
    if(x<=mid) ins(tr[p].lc,l,mid,x);
    else ins(tr[p].rc,mid+1,r,x);
}
inline int ask(int p,int l,int r,int x,int y){
    if(x>y) return 0;if(!p) return 0;
    if(x<=l&&r<=y) return tr[p].sum;
    int mid=l+r>>1,res=0;
    if(x<=mid) res+=ask(tr[p].lc,l,mid,x,y);
    if(y>mid) res+=ask(tr[p].rc,mid+1,r,x,y);
    return res;
}
inline int C(int x,int y){
    if(y>x) return 0;
    return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();K=read();fac[0]=inv[0]=inv[1]=1;
    for(int i=2;i<=n;++i) inv[i]=(ll)inv[mod%i]*(mod-mod/i)%mod;
    for(int i=1;i<=n;++i) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=(ll)inv[i-1]*inv[i]%mod;
    for(int i=1;i<=n;++i) a[i]=read(),ins(rt,0,nn,a[i]);
    for(int i=1;i<=n;++i){
        if(!a[i]){printf("%d\n",C(n,K));continue;}
        int res=0,x=ask(rt,0,nn,a[i],nn)-1+ask(rt,0,nn,0,(a[i]-1)/2);
        res+=C(x,K);int y=ask(rt,0,nn,a[i],min(a[i]*2-1,nn));
        x=ask(rt,0,nn,min(a[i]*2,nn),nn)+ask(rt,0,nn,0,a[i]-1);
        if(K-y>=0) res+=C(x,K-y);printf("%d\n",res%mod);
    }return 0;
}

你可能感兴趣的:(其他oj,线段树,组合数学)