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]))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
要么优秀要么生锈