CF-567C - Geometric Progression


我最初的时候枚举起点x,然后二分查找数值为x*k区间中的位置位于x之后的区间,然后在枚举区间的y(=x*k),用二分再求出y*k切在其之后的区间

这样写时间会t

后面发现枚举起点效率低,没有枚举中点效率高,因为枚举中点一可以剔除x%k!=0的

并且可以在lgn的时间内 查找到x/k和x*k的区间长度

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e5+100;
long long n,k,ans;
struct node{
    long long num;
    int pos;
    node(long long num,int pos):num(num),pos(pos){}
    node():num(0),pos(0){
    } 
    bool operator < (const node& rhy)const{
        return num<rhy.num||(num==rhy.num&&pos<rhy.pos);
    }
}a[maxn];
long long findcnt(long long x,int s,int e){
        return upper_bound(a,a+n,node(x,e-1))-lower_bound(a,a+n,node(x,s+1));
}


int main(){
    cin>>n>>k;
    for(int i=0;i<n;i++){
        cin>>a[i].num;
        a[i].pos=i;
    }
    ans=0;
    sort(a,a+n);
    if(n>=3){
        for(int i=0;i<n;i++){
            long long num=a[i].num;
            int pos=a[i].pos;
            if(num%k==0)
                ans+=findcnt(num/k,-1,pos)*findcnt(num*k,pos,n+1);
        }
    }
    cout<<ans<<endl;
    return 0;
}


看别人代码发现更加机智的写法,用两个map分别记录下第i位之前和之后的每个数字出现次数

然后~~~~~


 map<int,int> s, t;
        rep(i, n) ++ t[a[i]];
        ll ans = 0;
        rep(i, n) {
            int x = a[i];
            -- t[x];
            if(x % k == 0 && abs((ll)x * k) <= (ll)1e9)
                ans += (ll)s[x / k] * t[x * k];
            ++ s[x];
        }


 
 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值