zoukankan      html  css  js  c++  java
  • CF993E Nikita and Order Statistics

    IX.CF993E Nikita and Order Statistics

    首先,一上来就能想到的思路,对于(< x)的位置,赋成(1);对于(geq x)的位置,赋成(0),然后跑前缀和,设为(sum_x)。这样子,(x)在某个子串([l,r])中的排名就是(sum_r-sum_{l-1})

    (x)(sum)数组中出现了(cnt_x)次。则某个(k)的答案(ans_k=sum_{i=k}^ncnt_i*cnt_{i-k})。因为挑选任何一个(sum=i)的前缀与任何一个(sum=i-k)的前缀,都可以拼成一个(k)出来。

    遇事不决就翻转。我们设(f)表示原本的(cnt)(g)表示翻转((g_x=cnt_{n-x}))后的(cnt)

    则现在,(ans_{n-k}=sumlimits_{i+j=k}f_i*g_j)。是卷积的形式,直接FFT!!!

    不过有几个注意点:

    1.(sum_0),即空前缀和,也要计入(cnt),不然类似于串([1,r])的就不会被计入。估计只有我一个人才会忘记吧

    2.(ans_0)要特判,因为某些串你瞎卷卷可能卷出来长度为(0)的串。可以直接(O(n))暴力扫一遍即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const double pi=acos(-1);
    int n,m,cnt[1<<20],lg,lim=1,h[1<<20],rev[1<<20],sum[1<<20];
    struct cp{
    	double x,y;
    	cp(double u=0,double v=0){x=u,y=v;}
    	friend cp operator +(const cp &u,const cp &v){return cp(u.x+v.x,u.y+v.y);}
    	friend cp operator -(const cp &u,const cp &v){return cp(u.x-v.x,u.y-v.y);}
    	friend cp operator *(const cp &u,const cp &v){return cp(u.x*v.x-u.y*v.y,u.x*v.y+u.y*v.x);}
    }f[1<<20],g[1<<20];
    void FFT(cp *a,int tp){
    	for(int i=0;i<lim;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
    	for(int md=1;md<lim;md<<=1){
    		cp rt=cp(cos(pi/md),tp*sin(pi/md));
    		for(int stp=md<<1,pos=0;pos<lim;pos+=stp){
    			cp w=cp(1,0);
    			for(int i=0;i<md;i++,w=w*rt){
    				cp x=a[pos+i],y=w*a[pos+md+i];
    				a[pos+i]=x+y;
    				a[pos+md+i]=x-y;
    			}
    		}
    	}
    }
    int zero(){
    	int pos=0,res=0;
    	for(int i=1;i<=n;i++){
    		if(sum[i]!=sum[i-1])pos=i;
    		res+=i-pos;
    	}
    	return res;
    }
    signed main(){
    	scanf("%lld%lld",&n,&m);
    	while(lim<=n*2+1)lim<<=1,lg++;
    	for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
    	cnt[0]++;
    	for(int i=1,x;i<=n;i++)scanf("%lld",&x),sum[i]=sum[i-1]+(x<m),cnt[sum[i]]++;
    	for(int i=0;i<=n;i++)f[i]=cp(cnt[i],0),g[i]=cp(cnt[n-i],0);
    	FFT(f,1),FFT(g,1);
    	for(int i=0;i<lim;i++)f[i]=f[i]*g[i];
    	FFT(f,-1);
    	for(int i=0;i<=n;i++)h[n-i]=(int)(f[i].x/lim+0.5);
    	printf("%lld ",zero());
    	for(int i=1;i<=n;i++)printf("%lld ",h[i]);
    	return 0;
    }
    
  • 相关阅读:
    codeforces 455B A Lot of Games(博弈,字典树)
    HDU 4825 Xor Sum(二进制的字典树,数组模拟)
    hdu 1800 Flying to the Mars(简单模拟,string,字符串)
    codeforces 425A Sereja and Swaps(模拟,vector,枚举区间)
    codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)
    HDU 4148 Length of S(n)(字符串)
    codeforces 439D Devu and Partitioning of the Array(有深度的模拟)
    浅谈sass
    京东楼层案例思维逻辑分析
    浅谈localStorage和sessionStorage
  • 原文地址:https://www.cnblogs.com/Troverld/p/12772263.html
Copyright © 2011-2022 走看看