HDU-6315 Naive Operations 势能线段树 ai/bi

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

题意:给出一个初始值都为0的a数组,和一个给定值的b数组,然后q次操作,add l r,从l到r的范围的数字都加+1,query l r,查询ai/bi  l<=i<=r的和是多少

思路:(比赛的时候没有看清楚题意,错误的以为bi中的i是变化的,今天早上再看的时候发现,b数组不随i的变化而变化,尴尬了。)维护区间的a的最大值和b的最小值,使用lazy标记就不需要更新到每个点了,因为每次更新当当前最大值a小于最小的b,那么下面子节点就都不需要更新了,存贮在lazy中。当大于等于时我们暴力找到l==r然后cnt+1,同时分母+上b[l],比如当前是2/2 我们就把它变成 2/4 这样我们还需要增加2次才能到达4/4 再变成4/6.(巧妙的计算次数)。

所以相对于模板线段树来说,更新那里进行了修改,查询基本没有变,但是读错题目的我,以为ai/bi中bi的i是变化的,尴尬。

顺便去补补2-3道势能线段树。

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <set>
const int maxn = 1e5+5;
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
int b[maxn];
char s[50];
struct node
{
    int maxa;
    int minb;
    int cnt;
    int addv;

}tree[maxn*4];
void pushup(int rt)
{
    tree[rt].minb=min(tree[rt<<1].minb,tree[rt<<1|1].minb);
    tree[rt].maxa=max(tree[rt<<1].maxa,tree[rt<<1|1].maxa);
    tree[rt].cnt=tree[rt<<1].cnt+tree[rt<<1|1].cnt;
}
void pushdown(int rt)
{
    if(tree[rt].addv)                  //节点rt有标记
    {
        int v=tree[rt].addv;
        tree[rt<<1].maxa+=v;
        tree[rt<<1|1].maxa+=v;
        tree[rt<<1].addv+=v;
        tree[rt<<1|1].addv+=v;
        tree[rt].addv=0;
    }
}
void build(int l,int r,int rt)
{
    tree[rt].addv=0;
   // cout<<tree[rt].addv<<endl;
    if(l==r)
    {
         tree[rt].minb=b[l];
         tree[rt].maxa=0;
         tree[rt].cnt=0;
         return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)   //完全覆盖  L R  为输入的
    {
        tree[rt].maxa++;
        if(tree[rt].maxa<tree[rt].minb){
            tree[rt].addv++;
            return ;
        }
        if(l==r&&tree[rt].maxa>=tree[rt].minb){
            tree[rt].cnt++;
            tree[rt].minb+=b[l];
            return ;
        }
    }
    pushdown(rt);     //下传延迟标记
    int m=(l+r)>>1;
    if(L<=m) update(L,R,lson);
    if(m<R)  update(L,R,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return tree[rt].cnt;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    int  ret=0;
    if(L<=m) ret+=query(L,R,lson);
    if(m<R)  ret+=query(L,R,rson);
    return ret;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2){
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    build(1,n,1);
    while(m--){
        int a,b;
        scanf("%s %d %d",s,&a,&b);
        if(s[0]=='a')
           update(a,b,1,n,1);
        else
            printf("%d\n",query(a,b,1,n,1));
      }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/deepseazbw/article/details/81217562
今日推荐