题目链接:点击打开链接
题目大意:
题目描述
给一个数组{a},定义 h(a,b)为在十进制下 a + b 与 a 的位数差,求
,0的位数为1。
输入描述:
第一行读入一个正整数 n (1 <= n <= 105)。
第二行读入 n 个非负整数,第 i 个表示a[i] (0 <= a[i] <= 108)。
输出描述:
一行表示答案。
示例1
输入
10
0 1 2 3 4 5 6 7 8 9
输出
20
思路:
求出每个数a[i]进1位~进9位所需要的值x是多少,然后二分得出最初位置i,加上i后有多少个数大于等于x,
记录i后有多少个大于等于x的值需要用树状数组维护
这题巨特么傻逼,看了半天没发现自己傻逼了,人家a数组不能排序啊沃日,排序了就不对了啊,顺序就乱了啊,所以要用树状数组维护下标然后数出多个个数在原来数组中比你要求的数多,傻逼啊
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i<r;i++)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int epg=10-8;
const int maxn=1e5+10;
int a[maxn],b[maxn];
int c[maxn+55],pos[maxn];
ll sum[15]={0,0,10};
int n;
void add(int x)
{
for(;x<=n+55;x+=x&-x)
c[x]++;
}
int query(int x)
{
int ans=0;
while(x)
{
ans+=c[x];
x-=x&-x;
}
return ans;
}
int bit(int x)
{
int ans=0;
if(x==0)
return 1;
while(x)
{
x/=10;
ans++;
}
return ans;
}
int main()
{
//int n;
while(scanf("%d",&n)==1)
{
memset(pos,0,sizeof(pos));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
pos[i]=lower_bound(b+1,b+1+n,a[i])-b;
//for(int i=1;i<=n;i++)
//cout<<pos[i]<<endl;
for(int i=3;i<14;i++)
sum[i]=sum[i-1]*10;
ll ans=0;
for(int i=n;i>=1;i--)
{
int bits=bit(a[i]);
while(1)
{
bits++;
int cha=sum[bits]-a[i];
int xia=lower_bound(b+1,b+1+n,cha)-b-1;
if(xia==n)
break;
ans+=query(n)-query(xia);
}
add(pos[i]);
}
printf("%lld\n",ans);
}
return 0;
}