[explanation] sdoj2790 [Yali training 2017 Day1] market segment tree

It's amazing to change division into subtraction After writing, I was confused. I couldn't find out a sb mistake

Problem description

input

In the first line, the integer n,q separated by two spaces represent the number of vendors and the number of orders + inquiries respectively.

The second line contains n integers a0 ∼ an − 1 separated by spaces

Next, q line, each line represents an operation, the first number represents operation number 1 ∼ 4, and the following input is consistent with the problem description.

output

For each 3, 4 operation, output the query answer.

sample input

10 10
-5 -4 -3 -2 -1 0 1 2 3 4
1 0 4 1
1 5 9 1
2 0 9 3
3 0 9
4 0 9
3 0 1
4 2 3
3 4 5
4 6 7
3 8 9

sample output

-2
-2
-2
-2
0
1
1

For 30% data, n,q ≤ 10 ^ 3;

For 60% of the data, ensure that the data is random;

For 100% data, 1 ≤ n,q ≤ 10 ^ 5,0 ≤ l ≤ r ≤ n − 1,c ∈ [- 10^4,10^4],d ∈ [2,10 ^ 9]
(PS: there is a small mistake in the title description, which should be seen.)

Title Solution

Maintain interval sum, maximum value and minimum value. If the difference between the maximum value after division and the minimum value after division is the same, the difference can be marked (that is, the mark from division to interval subtraction)
It's been a long time since I checked it out )

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define lc (o<<1)
#define rc (o<<1|1)
#define mid (l+r>>1) 
int n,q;//Number of people, decree+Number of inquiries 
typedef long long ll;
const int N=1e5+10;
ll a[N];
ll sum[N<<2];
ll mx[N<<2];
ll mn[N<<2];
ll lazy[N<<2];
inline ll divide(ll x,ll y)
{
    return floor((double)x/y);
}
inline void push_up(int o)
{
    sum[o]=sum[lc]+sum[rc];
    mx[o]=max(mx[lc],mx[rc]);
    mn[o]=min(mn[lc],mn[rc]);
}
void build(int o,int l,int r)
{
    if(l==r)
    {
        mx[o]=mn[o]=sum[o]=a[l];
        lazy[o]=0;
        return;
    }
    build(lc,l,mid);build(rc,mid+1,r);
    #ifdef debug
    puts("-1");
    #endif
    push_up(o);
}
inline void push_down(int o,int l,int r)
{
    if(!lazy[o])return;
    lazy[lc]+=lazy[o];
    sum[lc]+=(mid-l+1)*lazy[o];
    mx[lc]+=lazy[o];
    mn[lc]+=lazy[o];
    lazy[rc]+=lazy[o];
    sum[rc]+=(r-mid)*lazy[o];
    mx[rc]+=lazy[o];
    mn[rc]+=lazy[o];
    lazy[o]=0;
    #ifdef debug
    puts("-2");
    #endif
}
void add(int o,int l,int r,int nl,int nr,ll v)
{
    if(l<r)push_down(o,l,r);
    if(nl<=l&&r<=nr)
    {
        sum[o]+=(ll)(r-l+1)*v;
        lazy[o]+=v;
        mn[o]+=v;
        mx[o]+=v;
        return;
    }
    if(nl<=mid)add(lc,l,mid,nl,nr,v);
    if(nr>mid)add(rc,mid+1,r,nl,nr,v);
    #ifdef debug
    puts("-3");
    #endif
    push_up(o);
}
void div(int o,int l,int r,int nl,int nr,ll v)
{
    if(l<r)push_down(o,l,r);
    if(nl<=l&&r<=nr)
    {
        ll m1=divide(mx[o],v);
        ll m2=divide(mn[o],v);
        if(mx[o]-m1==mn[o]-m2)
        {
            ll k=mx[o]-m1;
            sum[o]-=k*(r-l+1);//It has been written. k*(r-l+1)*vSurprised 
            mx[o]-=k;
            mn[o]-=k;
            lazy[o]-=k;
            return;
        }
    }
    if(nl<=mid)div(lc,l,mid,nl,nr,v);
    if(nr>mid)div(rc,mid+1,r,nl,nr,v);
    push_up(o);
    #ifdef debug
    puts("-4");
    #endif
}
ll query_min(int o,int l,int r,int nl,int nr)
{
    #ifdef debug
    puts("-5");
    #endif
    if(nl<=l&&r<=nr)
    return mn[o];
    push_down(o,l,r);
    if(nr<=mid)return query_min(lc,l,mid,nl,nr);
    else if(nl>mid)return query_min(rc,mid+1,r,nl,nr);
    else return min(query_min(lc,l,mid,nl,mid),query_min(rc,mid+1,r,mid+1,nr));
}
ll query_sum(int o,int l,int r,int nl,int nr)
{
    #ifdef debug
    puts("-6");
    #endif
    if(nl<=l&&r<=nr)
    return sum[o];
    push_down(o,l,r);
    if(nr<=mid)return query_sum(lc,l,mid,nl,nr);
    else if(nl>mid)return query_sum(rc,mid+1,r,nl,nr);
    else return query_sum(lc,l,mid,nl,mid)+query_sum(rc,mid+1,r,mid+1,nr);
} 
int main()
{
    //freopen("in.txt","r",stdin);  
    scanf("%d%d",&n,&q);
    int op,x,y;
    ll z;
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    build(1,1,n);
    for(int i=1;i<=q;i++)
    {
        scanf("%d",&op);
        if(op==1)
            scanf("%d%d%lld",&x,&y,&z),add(1,1,n,x+1,y+1,z);
        else if(op==2)
            scanf("%d%d%lld",&x,&y,&z),div(1,1,n,x+1,y+1,z);
        else if(op==3)
            scanf("%d%d",&x,&y),printf("%lld\n",query_min(1,1,n,x+1,y+1));
        else if(op==4)
            scanf("%d%d",&x,&y),printf("%lld\n",query_sum(1,1,n,x+1,y+1));
    }
    return 0;
}

Posted by kenle on Sun, 05 Jan 2020 02:36:48 -0800