• [机房测试]简单的打击


    Description

    具体的来说,两把剑分别代表了两个长度为 \(n\) 的序列 \(a,b\)

    你什么方面都强,所以你可以分别重新锻造这两把剑,锻造就相当于重新排列这两个序列。

    合并这两把剑,让它变成一把新剑(对应序列 \(c\)),合并相当于把对应位置上的数加起来 \(c_i=a_i+b_i\)

    最后你准备拿着这把新剑去找大 Boss,造成的伤害是众数出现的次数。

    问怎么排列才能使得伤害最大化,输出最大伤害。

    Solution

    考虑枚举这个众数 \(x\),那么该数最多出现

    \[\sum_{i=1}^{x-1} \min\{a_i,b_{x-i}\} \]

    看上去很像一个卷积,但是并不能直接处理。

    一个转换是

    \[\sum_{i=1}^{x-1} \min\{a_i,b_{x-i}\}=\sum_{k} \sum_{i=1}^{x-1} [a_i\geq k][b_{x-i} \geq k] \]

    可以枚举 \(k\),然后内层 FFT,但是这样复杂度是 \(O(|V|^2\log |V|)\) 的。会发现很多位置都是零,因为大于等于 \(k\) 的数至多有 \(\lfloor \frac{|V|}{k} \rfloor\) 个。那么可以考虑数据分治:
    · 对于 \(k\leq T\),用 FFT
    · 对于 \(k> T\),直接把还有值的数提取出来,然后暴力。
    实际测出来 \(T=4\)\(T=5\) 的时候,效率比较高。

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    #define db double
    #define rint register int
    
    const int N=(1<<20)+3;
    const db PI=acos(-1);
    
    struct Complex{
        db x,y;
        Complex(db x_=0,db y_=0):x(x_),y(y_){}
        Complex operator +(Complex a){return Complex(x+a.x,y+a.y);}
        Complex operator -(Complex a){return Complex(x-a.x,y-a.y);}
        Complex operator *(Complex a){return Complex(x*a.x-y*a.y,y*a.x+x*a.y);}
    }a[N<<1];
    
    int n,m,op,rk[N<<1];
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    void FFT(){
        for(rint i=0;i<n;i++)
            if(i<rk[i]) swap(a[i],a[rk[i]]);
        for(rint p=2;p<=n;p<<=1){
            int len=p>>1;
            Complex w(cos(2*PI/p),op*sin(2*PI/p));
            for(rint k=0;k<n;k+=p){
                Complex now=Complex(1.0,0.0);
                for(rint l=k;l<k+len;l++){
                    Complex t=now*a[l+len];
                    a[l+len]=a[l]-t;
                    a[l]=a[l]+t;
                    now=now*w;
                }
            }
        }
    }
    
    const int T=4;
    int A[N],B[N],ans[N],A_[N],B_[N],an,bn;
    
    int main(){
        freopen("hit.in","r",stdin);
        freopen("hit.out","w",stdout);
        n=read();
        for(rint i=1;i<=n;++i) A[read()]++;
        for(rint i=1;i<=n;i++) B[read()]++;
        for(m=2e5,n=1;n<=m;n<<=1);
        for(int i=0;i<n;i++)
            rk[i]=(rk[i>>1]>>1)|((i&1)? n>>1:0);
        for(int k=1;k<=T;k++){
            for(int i=0;i<n;i++)
                a[i].x=(A[i]>=k),a[i].y=(B[i]>=k);
            op=1,FFT();
            for(rint i=0;i<n;i++) a[i]=a[i]*a[i];
            op=-1,FFT();
            for(int i=0;i<=m;i++)
                ans[i]+=((int)(a[i].y/n/2+0.5));
        }
        for(int i=1;i<=n;i++){
            if(A[i]>T) A_[++an]=i;
            if(B[i]>T) B_[++bn]=i;
        }
        for(int i=1;i<=an;i++)
            for(int j=1;j<=bn;j++)
                ans[A_[i]+B_[j]]+=min(A[A_[i]],B[B_[j]])-T;
        int ret=0;
        for(int i=0;i<n;i++) ret=max(ret,ans[i]);
        printf("%d",ret);
    }
    
  • 相关阅读:
    C++中的关键概念:名字查找与继承
    调用哪个虚函数的问题
    二叉树基础知识
    赫夫曼树及其应用
    用MyEclipse搭建SSH框架 Struts Spring Hibernate
    数据库 事务的特性ACID
    网桥与交涣机
    Adobe Edge Animate 1.0 概述
    【官方】Adobe Edge Preview 3 初学者指南
    Adobe Edge , Flash 未来的方向?
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15426476.html
Copyright © 2020-2023  润新知