您的位置:首页 > 其它

CF-567C - Geometric Progression

2015-08-06 04:52 357 查看
<span style="font-size: 1em; line-height: 1.4em; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; background-color: rgb(255, 255, 255);">这道题,我用一个结构体储存数值和位置,然后二次排序</span>


我最初的时候枚举起点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];
        }



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: