大致题意:给定一个序列,求图片说明 .
图片说明 表示图片说明图片说明 十进制下的位数差.
图片说明
分析:
方法一:离散+树状数组
我们可以逆序遍历序列,计算当前图片说明 作为图片说明 的左参数的贡献,那么我们与图片说明 相加能产生数位差图片说明 .举个例子:能至少产生一位数位差,设比图片说明 大的最小十进制数位图片说明 ,那么图片说明 的大小一定要大于等于图片说明 .依次枚举至少产生两位数位差.....其实就是遍历所有的十进制数字进行查找.
那么当我们求解图片说明 的数位差贡献时,必须要有一个数据结构存储图片说明 ,并且使其有序才能进行二分查找符合条件的图片说明 的个数。-------离散所有可能出现的值(大概9e5),然后树状数组维护即可.

#include<bits/stdc++.h>
#define lowbit(x) x&(-x)

using namespace std;

typedef long long ll;
const int maxn=2e5+10;
int a[maxn],sum[maxn*9];

int n;
vector<int> p;
vector<int> p1;
int cnt;
void add( int x ) { while( x<=cnt ) sum[x]++,x+=lowbit(x); }
int get_sum( int x ,int ans=0 ) { while( x ) ans+=sum[x],x-=lowbit(x);return ans; }

int get_id( int x )
{
    return lower_bound(p1.begin(),p1.end(),x)-p1.begin()+1;
}

int main()
{
    cin>>n;
    for( int i=1,num=10;i<=9;i++,num*=10 )  p.push_back(num);
    for( int i=1;i<=n;i++ ) scanf("%d",&a[i]);

    for( int i=1;i<=n;i++ )
    {
        for( int j=0;j<9;j++ )   if( a[i]>p[j] )  p1.push_back(p[j]-a[i]);
        p1.push_back(a[i]);
    }
    sort(p1.begin(),p1.end());
    cnt=p1.size();

    ll ans=0;
    for( int i=n;i>=1;i-- )
    {
        for( int j=0;j<9;j++ )
        {
            if( a[i]>=p[j] ) continue;
            int pos=get_id(p[j]-a[i]);
            ans+=get_sum(cnt)-get_sum(pos-1);  
        }
        add(get_id(a[i]));
    }
    printf("%lld\n",ans);
}

方法二:分治
二分区间长度,分治每个区间的数位差贡献,合并计算时,对于当前左右区间,对右区间进行排序,遍历左区间图片说明 进行求图片说明 在右区间符合条件的个数。查找条件和方法一类似。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn=2e5+10;
int a[maxn],sum[maxn];

ll b[10];

ll solve( int l,int r )
{
    if( r==l ) return 0;
    int mid=(l+r)/2;
    ll res=solve(l,mid)+solve(mid+1,r);
    sort(a+mid+1,a+r+1);
    for( int i=l;i<=mid;i++ )
    {
        for( int j=0;j<9;j++ ) 
        {
            if( b[j]-a[i]>0 ) 
            res+=a+r+1-lower_bound(a+mid+1,a+r+1,b[j]-a[i]);
        }
    }
    return res;
}


int main()
{
    int n;cin>>n;b[0]=10;for( int i=1;i<9;i++ ) b[i]=b[i-1]*10;
    for( int i=1;i<=n;i++ ) cin>>a[i];
    cout<<solve(1,n)<<endl;
}