Wannafly挑战赛3

B.遇见

签到


 

 

C.位数差


 题意

给一个数组{a},定义 h(a,b)为在十进制下 a + b 与 a 的位数差,求 ,0的位数为1

(1 <= n <= 1e5,0 <= a[i] <= 108)
分析
由题意考虑每一个a,其位置后有不同的b,且对答案的贡献不同,故考虑转换一下角度,将数组反转,考虑每一个a的时候,直接考虑a位置前的b即可,所以不难想到需要处理每一个a后将其有用的信息保存下来,在这里我们可以开一颗线段树但a[i]有1e8,故考虑动态分配节点即可,每次统计所有的情况的位数差,然后将a【i】信息更新即可,具体细节还需要扣一扣
时间复杂度O(n*log(a[i]))
 
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e7 + 10;
const int INF = 1e8+100;
int tree[maxn], lson[maxn], rson[maxn];
int tot=1;
int a[100005];
int num[10];
int n;
int root=1;

int newnode()
{
    ++tot;
    tree[tot] = lson[tot] = rson[tot] = 0;
    return tot;
}

void update(int &x, int l, int r, int val)
{
    if(!x)
        x=newnode();
    tree[x]++;
    if(l == r)
        return;
    int mid = (l+r)>>1;
    if(val<=mid ) update(lson[x], l, mid, val);
    else   update(rson[x], mid+1, r, val);
}

int query(int x, int l, int r, int ql, int qr)
{
    if(ql<=l && qr>=r)
        return tree[x];
    int mid = (l + r)>> 1;
    int ans = 0;
    if(ql<=mid && lson[x]) ans +=query(lson[x], l , mid, ql, qr);
    if(qr>mid && rson[x]) ans+=query(rson[x], mid+1, r, ql, qr);
    return ans;
}

int main()
{
    int n, l ,r;
    num[0] = 0, num[1] = 1;
    for(int i = 2; i <= 9; i++)
        num[i]=num[i-1]*10;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[n-i+1]);
    }
    ll ans=0;
    for(int i = 1; i <= n; i++)
    {
        int p=upper_bound(num, num+10,a[i])-num;
        if(p==1)
            p++;
        for(int j = p; j <= 9; j++)
        {
            ans+=(query(root, 0, INF, num[j], 10*num[j]+-1))*(j-p+1);
            ans+=query(root, 0, INF, num[j]-a[i], num[j]-1);
        }
        update(root, 0, INF, a[i]);
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

 

posted @ 2017-11-14 22:08  Superwalker  阅读(152)  评论(0编辑  收藏  举报