杭电多校第二场 Naive Operations(线段树区间更新+单点更新)

 Naive Operations

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


 

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=l⌊ai/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≤l≤r≤n, 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

题意:两个序列,a和b序列,a序列的初始值全部为0,b序列的值由题目给出,为n的任意一个排列,现在有两种操作:

  1. 给区间[l,r]的a序列全部加上1
  2. 查询区间[l,r]的⌊ai/bi⌋和的值

思路:很明显是道线段树的题,比赛时只想到了维护a序列的最大值,维护b序列的最小值,如果区间都加1之后a的最大值比b的最小值还小,则这个区间要维护的和不变,只需加个lazy标记就行了,然后就不知道怎么处理了,实际上如果区间a的最大值比b的最小值大的情况,我们就一直更新到a比b大的根节点,把根节点维护的和加一,然后根节点的b的最小值再加上初始的b

然后晚上听了大佬的解法,维护了一个a还需加多少等于b的最小值,当更新到一个区间,这个区间的最小值减掉1,如果最小值不等于0,直接加个lazy就行了,如果最小值等于0的话,就一直更新的最小值等于0的根节点,把这个根节点要维护的和加1,然后再把最小值更新为b的初始值

这道题其实是把区间更新和单点更新给结合了起来,至于时间复杂度会不会超,好像可以证明,和级数有关

第一个思路的写法

#include <stdio.h>
#include <iostream>

using namespace std;

#define lson num << 1
#define rson num << 1 | 1

const int MAXN = 100005;
struct node
{
    int l,r,lazy;
    int minb,maxa,sum,b;
}tree[MAXN << 2];
void pushup(int num)
{
    tree[num].minb = min(tree[lson].minb,tree[rson].minb);
    tree[num].maxa = max(tree[lson].maxa,tree[rson].maxa);
    tree[num].sum = tree[lson].sum + tree[rson].sum;
}
void build(int num,int l,int r)
{
    tree[num].l = l;
    tree[num].r = r;
    tree[num].lazy = 0;
    if(l == r) {
        tree[num].sum = 0;
        scanf("%d",&tree[num].b);
        tree[num].minb = tree[num].b;
        tree[num].maxa = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson,l,mid);
    build(rson,mid + 1,r);
    pushup(num);
}
void pushdown(int num)
{
    if(tree[num].lazy) {
        tree[lson].maxa += tree[num].lazy;
        tree[rson].maxa += tree[num].lazy;
        tree[lson].lazy += tree[num].lazy;
        tree[rson].lazy += tree[num].lazy;
        tree[num].lazy = 0;
    }
}
void update(int num,int l,int r)
{
    if(tree[num].l == l && tree[num].r == r ) {
        tree[num].maxa++;
        if(tree[num].maxa < tree[num].minb) {
            tree[num].lazy++;
            return;
        }
        if(tree[num].l ==  tree[num].r && tree[num].maxa >= tree[num].minb) {
            tree[num].sum++;
            tree[num].minb += tree[num].b;
            return;
        }
    }
    pushdown(num);
    int mid = (tree[num].l + tree[num].r) >> 1;
    if(r <= mid) update(lson,l,r);
    else if(l > mid) update(rson,l,r);
    else {
        update(lson,l,mid);
        update(rson,mid + 1,r);
    }
    pushup(num);
}
int query(int num,int l,int r)
{
    if(tree[num].l == l && tree[num].r == r) {
        return tree[num].sum;
    }
    int mid = (tree[num].l + tree[num].r) >> 1;
    if(r <= mid) return query(lson,l,r);
    else if(l > mid) return query(rson,l,r);
    else return query(lson,l,mid) + query(rson,mid + 1,r);
    pushup(num);
}
int main(void)
{
    int n,m,l,r;
    char op[5];
    while(scanf("%d%d",&n,&m) != EOF) {
        build(1,1,n);
        while(m--) {
            scanf("%s%d%d",op,&l,&r);
            if(op[0] == 'a') {
                update(1,l,r);
            }
            else {
                printf("%d\n",query(1,l,r));
            }
        }
    }
    return 0;
}


---------第二种写法-----------
#include <stdio.h>
#include <iostream>

using namespace std;

#define lson num << 1
#define rson num << 1 | 1

const int MAXN = 100005;
struct node
{
    int l,r,lazy;
    int Min,sum,b;
}tree[MAXN << 2];
void pushup(int num)
{
    tree[num].Min = min(tree[lson].Min,tree[rson].Min);
    tree[num].sum = tree[lson].sum + tree[rson].sum;
}
void build(int num,int l,int r)
{
    tree[num].l = l;
    tree[num].r = r;
    tree[num].lazy = 0;
    if(l == r) {
        tree[num].sum = 0;
        scanf("%d",&tree[num].b);
        tree[num].Min = tree[num].b;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson,l,mid);
    build(rson,mid + 1,r);
    pushup(num);
}
void pushdown(int num)
{
    if(tree[num].lazy < 0) {
        tree[lson].Min += tree[num].lazy;
        tree[rson].Min += tree[num].lazy;
        tree[lson].lazy += tree[num].lazy;
        tree[rson].lazy += tree[num].lazy;
        tree[num].lazy = 0;
    }
}
void update(int num,int l,int r)
{
    if(tree[num].l == l && tree[num].r == r) {
        tree[num].Min--;
        if(tree[num].Min) {
            tree[num].lazy--;
            return;
        }
        else if(tree[num].l == tree[num].r) {
                tree[num].sum++;
                tree[num].Min = tree[num].b;
                return;
        }
    }
    pushdown(num);
    int mid = (tree[num].l + tree[num].r) >> 1;
    if(r <= mid) update(lson,l,r);
    else if(l > mid) update(rson,l,r);
    else {
        update(lson,l,mid);
        update(rson,mid + 1,r);
    }
    pushup(num);
}
int query(int num,int l,int r)
{
    if(tree[num].l == l && tree[num].r == r) {
        return tree[num].sum;
    }
    //pushdown(num);
    int mid = (tree[num].l + tree[num].r) >> 1;
    if(r <= mid) return query(lson,l,r);
    else if(l > mid) return query(rson,l,r);
    else return query(lson,l,mid) + query(rson,mid + 1,r);
    pushup(num);
}
int main(void)
{
    int n,m,l,r;
    char op[5];
    while(scanf("%d%d",&n,&m) != EOF) {
        build(1,1,n);
        while(m--) {
            scanf("%s%d%d",op,&l,&r);
            if(op[0] == 'a') {
                update(1,l,r);
            }
            else {
                printf("%d\n",query(1,l,r));
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/81265012
今日推荐