版权声明:转载记得标明出处哦~ https://blog.csdn.net/weixin_43890047/article/details/89048175
先贴代码:
#include<bits/stdc++.h>
using namespace std;
int bit[30]; ///维护的树状数组只有28(27+1,存到1~n的区间中)长,排名系列
const int MAX_N = 2e5+50;
int ans[MAX_N];
/**注意这个结构体的写法
***这个是询问的顺序
***而当把询问的问题与他的下标一同存在结构体内
***就可以将问题进行排序或相关的预处理,而询问的下标不会发生改变
***在离散化处理中也有类似操作
**/
struct node
{
int val;
int ind;
}numbers[MAX_N]; ///询问次数
bool operator < (const node &A,const node &B)
{
return A.val<B.val;
}
int ABS(int x)
{
return x<0?-x:x;
}
int lowbit(int x)
{
return x&(-x);
}
///注意维护的区间到底是什么,是维护询问问题还维护解,而这个问题就是维护解
///这个可以把解看成排名,这个问题就是在问xx问题前面有多少比他小的
///而解法就是对询问进行排序,然后用for(询问) while(到询问之前) ; 进行处理
void change(int x,int v)
{
for(;x<=28;x+=lowbit(x)){
bit[x]+=v;
}
}
int getsum(int x)
{
int res = 0;
for(;x;x-=lowbit(x)){
res+=bit[x];
}
return res;
}
int cal(int x)
{
int p = x/1000;
int q = x%1000;
return ABS(p/100 + (p/10)%10 + p%10 - q/100 - (q/10)%10 - q%10);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&numbers[i].val);
numbers[i].ind = i;
}
sort(numbers+1,numbers+1+n);
for(int i=1,q=0;i<=n;i++){
while(q<numbers[i].val) change(cal(q++)+1,1);
ans[numbers[i].ind] = getsum(cal(q));
}
for(int i=1;i<=n;i++){
printf("%d\n",ans[i]);
}
return 0;
}
- 总结:
- 1、要知道维护的区间长度和区间对应的含义是什么
- 2、这个是问某一个点前面的有比他小的解的个数,可把问题引申为一堆问题,每个问题询问前面比他大(小)的解的个数,那么解法就是为询问创一个结构体,将询问顺序和询问问题存在结构体中,对询问进行排序,利用 for(询问) while(到询问之前) ; 进行处理解法。