• [BZOJ 1145] 图腾totem


    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1145

    Solution:

    算是一道神题了吧

    设 f(abcd)为:当选出的四个数相对大小关系为abcd时,有多少种选择方式 

    则 res = f(1324) - f(1243) -f(1432)

    拆分法转化此问题
    f(1324) = f(1x2x) - f(1423)
    f(1243) = f(12xx) - f(1234)
    f(1432) = f(14xx) - f(1432)


    所以res = f(1x2x) + f(1234) - f(12xx) - f(14xx)
                 = f(1x2x) + f(1234) + f(13xx) - f(1xxx)

    预处理求出l[i],r[i]表示在i的左/右,比a[i]小的个数

    可以先用树状数组求l[i],则r[i]=(a[i]-l[i]-1)

    接下来对每一种情况分类讨论即可:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    
    const int MAXN=2e5+10;
    const int MOD=16777215;
    
    int n,dat[MAXN],bit[MAXN],l[MAXN],r[MAXN];
    
    void Update(int pos,int val)
    {
        while(pos<=n)
            bit[pos]+=val,pos+=pos&(-pos);
    }
    
    int Query(int pos)
    {
        int ret=0;
        while(pos)
            ret+=bit[pos],pos-=pos&(-pos);
        return ret;
    }
    
    int cal1()//1x2x
    {
        memset(bit,0,sizeof(bit));int ret=0;
        for(int i=1;i<=n;i++)
            ret=(ret+((1ll*(n-i-r[i])*(l[i]*(i-2)-Query(dat[i])-l[i]*(l[i]-1)/2))&MOD))&MOD,
            Update(dat[i],i-1);
        return ret;
    }
    
    int cal2()//1234
    {
        memset(bit,0,sizeof(bit));int ret=0;
        for(int i=1;i<=n;i++)
            ret=(ret+(1ll*(n-i-r[i])*Query(dat[i])&MOD))&MOD,
            Update(dat[i],l[i]);
        return ret;
    }
    
    int cal3()//13xx
    {
        memset(bit,0,sizeof(bit));int ret=0;
        for(int i=n;i>0;i--)
            ret=(ret+(1ll*(n-r[i]-i)*(Query(dat[i])-r[i]*(r[i]-1)/2)&MOD))&MOD,
            Update(dat[i],dat[i]-1);
        return ret;
    }
    
    int cal4()//1xxx
    {
        memset(bit,0,sizeof(bit));int ret=0;
        for(int i=1;i<=n;i++)
        {    
            int t=n-i-r[i];
            ret=(ret+(1ll*t*(t-1)*(t-2)/6&MOD))&MOD;
        }
        return ret;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&dat[i]);
            l[i]=Query(dat[i]);r[i]=dat[i]-1-l[i];
            Update(dat[i],1);
        }
        
        printf("%d",(cal1()+cal2()+cal3()-cal4()+MOD+1)&MOD);
        return 0;
    }

    Review:

    1、16777216是2的24次方

          可以用按位与来优化mod

    2、思路的借鉴:

    一般此类序列性问题,当每一位都确定时反而难以求解

    于是我们将确定转化为不确定来统一计算答案

  • 相关阅读:
    Fragment+ViewPager实现仿微信点击和滑动切换界面
    Android:控件WebView显示网页
    Android:控件WebView显示网页
    蓝桥杯 算法训练 数字三角形
    蓝桥杯 算法训练 数字三角形
    [置顶] Netty学习总结(1)——Netty入门介绍
    Git学习总结(7)——Git GUI学习教程
    Linux学习总结(12)——Linux必须学会的60个命令
    程序猿学习资料集
    Spring学习总结(14)——Spring10种常见异常解决方法
  • 原文地址:https://www.cnblogs.com/newera/p/9102788.html
Copyright © 2020-2023  润新知