CodeForces - 1117G

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011528035/article/details/87888966

思路:如果我们只考虑一个点在一个区间内所提供的贡献,那么只要需要知道左第一个比他大的数离他的距离和右边第一个数比他的距离即可。而两边处理步骤是一样的,因此,可以先算完左边,在算右边。首先先对询问离散化处理,然后使用单调队列预处理出每个点最左或最右的位置,然后使用两个树状数组储存,并计算答案。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn = 1e6 + 10;
#define IO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
inline int read() {
    char c = getchar(); int x = 0;
    while (c < '0' || c > '9') { c = getchar(); }
    while (c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c & 15); c = getchar(); }
    return x;
}


struct Node{
    int val;
    int pos;

    Node(int v,int p){
        val=v;
        pos=p;
    }

    Node(){
    }
};

struct Query{
    int id;
    int l;
    int r;
};

int cmp(Query q1,Query q2){
    return q1.l<q2.l;
}

Node a[maxn];
Query q[maxn];


LL bit1[maxn];
LL bit2[maxn];

LL ans[maxn];
int p[maxn];

vector<int> v[maxn];

int tail=0;
int n,m;

int add(Node node){

    while(tail&&a[tail-1].val<node.val){
        tail--;
    }
    a[tail++]=node;
    if(tail==1){
        return node.pos;
    }
    else{
        return a[tail-2].pos;
    }
}

int lowbit(int x)
{
    return x&(-x);
}


void add1(int x,int i)
{
    while(i<=n)
    {
        bit1[i]+=x;
        i+=lowbit(i);
    }
}

void add2(int x,int i)
{
    while(i<=n)
    {
        bit2[i]+=x;
        i+=lowbit(i);
    }
}

LL sum1(int i)
{
    LL s=0;
    while(i>0)
    {
        s+=bit1[i];
        i-=lowbit(i);
    }
    return s;
}

LL sum2(int i)
{
    LL s=0;
    while(i>0)
    {
        s+=bit2[i];
        i-=lowbit(i);
    }
    return s;
}

void solve(){

    sort(q+1,q+m+1,cmp);
    memset(bit1,0,sizeof(bit1));
    memset(bit2,0,sizeof(bit2));
    tail=0;

    for(int i=1;i<=n;i++){
        v[i].clear();
    }

    for(int i=1;i<=n;i++){
        int pos=add(Node(p[i],i));
        if(pos==i){
            add1(pos,i);
        }
        else{
            add1(i-pos,i);
            add2(1,i);
            v[pos].push_back(i);
        }
    }

    int cur=0;
    for(int i=1;i<=m;i++){

        if(q[i].l>cur){

            for(;cur<q[i].l-1;cur++){

                for(int k=0;k<v[cur].size();k++){

                    int l=v[cur][k];
                    add1(cur,l);
                    add2(-1,l);
                }
            }
        }

        ans[q[i].id]-=((q[i].r-q[i].l+1)-(sum2(q[i].r)-sum2(q[i].l-1)))*cur;
        ans[q[i].id]+=sum1(q[i].r)-sum1(q[i].l-1);
    }
}

int main() {

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        p[i]=read();
    }

    for(int i=1;i<=m;i++){
        //scanf("%d",&q[i].l);
        q[i].l=read();
    }

    for(int i=1;i<=m;i++){
        q[i].id=i;
        q[i].r=read();
        ans[i]-=(q[i].r-q[i].l+1);
    }

    solve();

    for(int i=1;2*i<=n;i++){
        swap(p[i],p[n-i+1]);
    }

    for(int i=1;i<=m;i++){
        int t=q[i].r;
        q[i].r=n-q[i].l+1;
        q[i].l=n-t+1;
    }
    solve();

    for(int i=1;i<=m;i++)
        printf("%lld\n",ans[i]);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u011528035/article/details/87888966
今日推荐