HDU 6315 2018HDU多校赛第二场 Naive Operations(线段树+树状数组)

Naive Operations

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Others)
Total Submission(s): 282    Accepted Submission(s): 78

Problem Description

In a galaxy far, far away, there are two integer sequence a and b of length n.
b is a static permutation of 1 to n. Initially a is filled with zeroes.
There are two kind of operations:
1. add l r: add one for al,al+1...ar
2. query l r: query ∑ri=lai/bi

Input

There are multiple test cases, please read till the end of input file.
For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
In the second line, n integers separated by spaces, representing permutation b.
In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
1≤n,q≤100000, 1≤lrn, there're no more than 5 test cases.

Output

Output the answer for each 'query', each one line.

Sample Input

 

5 12

1 5 2 4 3

add 1 4

query 1 4

add 2 5

query 2 5

add 3 5

query 1 5

add 2 4

query 1 4

add 2 5

query 2 5

add 2 2

query 1 5

Sample Output

 

1

1

2

4

4

6

Source

2018 Multi-University Training Contest 2

大致题意:初始的时候给你序列bi,然后ai初始为0。现在又两种操作add l r 和query l r。add是把a中区间[l,r]加一,query是让你求∑⌊ai/bi⌋,即区间内ai数值除以bi向下取整。

个人最擅长做的题系列~现场50min时A题O(∩_∩)O……

首先说明一下,这里用普通的线段树维护区间和之后再去除法,什么通分什么的都不行。因为这里的次序是先向下取整再进行求和。所以得考虑用其他的方法。仔细观察,我们可以发现,只有当ai的数值增加了bi的时候,才会对最后的结果产生贡献。因此,我们完全可以利用这个性质,把问题分成两个,一个是维护ai的数值增量,另一个是维护最后的结果。

数值增量我们用线段树来维护,每次区间修改,那么问题在于如何判定每一个ai是否已经到了对应bi呢?这里利用一些黑科技,我首先我线段树中的每个数值赋值为-bi,然后每次对相应区间进行加一。这样的话,如果一个ai等于bi的时候,那么它对应在线段树中的值就是0,于是我们就可以通过判断所有数字中的最大值来确定是否有ai等于bi。当整个区间最大值等于0的时候,我们把对应位置的最后答案贡献加一,同时在线段树中把它的值重新赋值为-bi,然后继续判断。

这样,我们就是每次修改之后,可以判断出哪些东西对最后会有影响。然后统计最后影响的时候,我们就用树状数组统计,这就变成了一个单点修改、区间查询的问题了。具体见代码:

#include<bits/stdc++.h>
#define mod 1000000007
#define LL long long
#define N 150010
using namespace std;

typedef pair<int,int> PII;
int b[N],n;
LL c[N];

struct ST
{

    struct node{PII max; int l,r,lazy;} tree[N<<2];

    inline void push_up(int i)
    {
        tree[i].max=max(tree[i<<1].max,tree[i<<1|1].max);
    }

    inline void build(int i,int l,int r)
    {
        tree[i]=node{PII(0,0),l,r,0};
        if (l==r)
        {
            tree[i].max=PII(-b[l],l);
            return;
        }
        int mid=(l+r)>>1;
        build(i<<1,l,mid);
        build(i<<1|1,mid+1,r);
        push_up(i);
    }

    inline void push_down(int i)
    {
        tree[i<<1].lazy+=tree[i].lazy;
        tree[i<<1|1].lazy+=tree[i].lazy;
        tree[i<<1].max.first+=tree[i].lazy;
        tree[i<<1|1].max.first+=tree[i].lazy;
        tree[i].lazy=0;
    }

    inline void update(int i,int l,int r,int x)
    {
        if ((tree[i].l==l)&&(tree[i].r==r))
        {
            tree[i].lazy+=x;
            tree[i].max.first+=x;
            return;
        }
        if (tree[i].lazy!=0) push_down(i);
        int mid=(tree[i].l+tree[i].r)>>1;
        if (mid>=r) update(i<<1,l,r,x);
        else if (mid<l) update(i<<1|1,l,r,x);
        else
        {
            update(i<<1,l,mid,x);
            update(i<<1|1,mid+1,r,x);
        }
        push_up(i);
    }

    inline PII getmax(int i,int l,int r)
    {
        if ((tree[i].l==l)&&(tree[i].r==r)) return tree[i].max;
        if (tree[i].lazy!=0) push_down(i);
        int mid=(tree[i].l+tree[i].r)>>1;
        if (mid>=r) return getmax(i<<1,l,r);
        else if (mid<l) return getmax(i<<1|1,l,r);
        else return max(getmax(i<<1,l,mid),getmax(i<<1|1,mid+1,r));
    }

} seg;

void update(int x)
{
    for(int i=x;i<N;i+=i&-i)
        c[i]++;
}

LL sum(LL x)
{
    if (x<=0) return 0;
    LL res=0;
    for(int i=x;i;i-=i&-i)
        res+=c[i];
    return res;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n,q;
    while(cin>>n>>q)
    {
        for (int i = 1; i <= n; ++i)
        {
            cin>>b[i];
        }
        seg.build(1,1,n);
        for(int i=1;i<=n;i++) c[i]=0;
        while(q--)
        {
            int l,r;
            char op[10];
            cin>>op>>l>>r;
            if (op[0]=='a')
            {
                seg.update(1,l,r,1);
                PII tmp=seg.getmax(1,l,r);
                while(tmp.first==0)
                {
                    seg.update(1,tmp.second,tmp.second,-b[tmp.second]);
                    update(tmp.second); tmp=seg.getmax(1,l,r);
                }
            } else
            {
                cout<<sum(r)-sum(l-1)<<endl;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u013534123/article/details/81208444
今日推荐