F. Tickets——东二

版权声明:转载记得标明出处哦~ 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(到询问之前) ; 进行处理解法。

猜你喜欢

转载自blog.csdn.net/weixin_43890047/article/details/89048175