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

    题目大意:

    给你一个数组 (a_{1 sim n}),对于 (k = 0 sim n),求出有多少个数组上的区间满足:区间内恰好有 (k) 个数比 (x) 小。(x) 为一个给定的数。

    (n le 2 imes 10^5)

    没见过大概想不到飞飞兔吧

    考虑(n)(10w)级别,且要求求(0sim n)的每个(k),考虑(fft)

    由于(x)是一定的,所以我们可以把小于(x)的数字变为(1),其他变为(0)

    (s_i)为变化后序列前缀和,(f_i=sumlimits_{j=0}^{n}[s_j==i])

    那么我们要求

    [sumlimits_{i=k}^{n}f_i*f_{i-k} ]

    这个东西是不能(fft)的,对后面变化一下

    [sumlimits_{i=k}^{n}f_i*f_{n-(n+k-i)} ]

    (j=n+k-i)

    [sumlimits_{i+j=n+k}f_i*f_{n-j} ]

    (g_i=f_{n-i})

    [sumlimits_{i+j=n+k}f_i*g_j ]

    它已经散发出毒品的香气了

    不过注意当(k=0)时会重复计算左右端点,需要特判

    一些细节证明先留锅,不太明白

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define int long long
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=1e6+10;
    	double pi=acos(-1.0);
    	int n,tmp,limit,len;
    	int a[N],pos[N],ret[N];
    	int sum[N];
    	struct complex
    	{
    		double x,y;
    		complex(double tx=0,double ty=0){x=tx,y=ty;}
    		inline complex operator + (const complex &t) const
    		{
    			return complex(x+t.x,y+t.y);
    		}
    		inline complex operator - (const complex &t) const
    		{
    			return complex(x-t.x,y-t.y);
    		}
    		inline complex operator * (const complex &t) const
    		{
    			return complex(x*t.x-y*t.y,x*t.y+y*t.x);
    		}
    	}f[N],g[N];
    	inline void fft(int limit,complex *a,int inv)
    	{
    		for(int i=0;i<limit;++i)
    			if(i<pos[i]) swap(a[i],a[pos[i]]);
    		for(int mid=1;mid<limit;mid<<=1)
    		{
    			complex Wn(cos(pi/mid),inv*sin(pi/mid));
    			for(int r=mid<<1,j=0;j<limit;j+=r)
    			{
    				complex w(1,0);
    				for(int k=0;k<mid;++k,w=w*Wn)
    				{
    					complex x=a[j+k],y=w*a[j+k+mid];
    					a[j+k]=x+y;
    					a[j+k+mid]=x-y;
    				}
    			}
    		}
    	}
    	inline void main()
    	{
    		n=read(),tmp=read();
    		for(int i=1;i<=n;++i) a[i]=(read()<tmp),sum[i]=sum[i-1]+a[i];
    		f[0].x=1;
    		for(int tmp=0,i=1;i<=n;++i)
    		{
    			tmp+=a[i];
    			++f[tmp].x;
    		}
    		for(int i=0;i<=n;++i) g[i].x=f[n-i].x;
    		for(limit=1;limit<=n+n;limit<<=1) ++len;
    		for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
    		fft(limit,f,1);
    		fft(limit,g,1);
    		for(int i=0;i<limit;++i) f[i]=f[i]*g[i];
    		fft(limit,f,-1);
    		for(int tmp=0,sum=0,i=1;i<=n;++i)
    		{
    			if(!a[i]) ++sum;
    			else
    			{
    				tmp+=((sum+1)*sum)>>1;
    				sum=0;
    			}
    			if(i==n)
    			{
    				tmp+=((sum+1)*sum)>>1;
    				printf("%lld ",tmp);
    			}
    		}
    		for(int i=n+1;i<=n+n;++i) ret[i]=f[i].x/limit+0.5;
    		for(int i=n+1;i<=n+n;++i) printf("%lld ",ret[i]);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    
  • 相关阅读:
    教你怎么叠T恤
    最动人的情歌《The Power of Love》by Celine.Dion
    使代码简洁的 5 条忠告
    Timeout MessageBox
    内联函数
    局部对象
    const用法(转)
    心情
    内联函数
    局部对象
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12051604.html
Copyright © 2011-2022 走看看