码迷,mamicode.com
首页 > 其他好文 > 详细

loj6029 「雅礼集训 2017 Day1」市场

时间:2017-06-11 23:19:56      阅读:564      评论:0      收藏:0      [点我收藏+]

标签:div   targe   pen   get   fine   nbsp   gis   max   线段树   

传送门:https://loj.ac/problem/6029

【题解】

考虑如果有一些近似连续的段

比如 2 2 2 3 3 3,考虑在除3意义下,变成0 0 0 1 1 1,相当于整体-2

又:区间增加很容易造成这种段,所以我们猜测可以暴力维护

用一棵线段树即可。(好像真的能暴力维护啊 我不知道怎么证明复杂度)

技术分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 4e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, a[M]; 
struct SMT {
    ll mx[M], mi[M], s[M], tag[M];
    # define ls (x<<1)
    # define rs (x<<1|1)
    inline void up(int x) {
        s[x] = s[ls] + s[rs];
        mx[x] = max(mx[ls], mx[rs]);
        mi[x] = min(mi[ls], mi[rs]);
    }
    inline void pushtag(int x, ll tg, int len) {
        mx[x] += tg;
        mi[x] += tg;
        s[x] += tg*len;
        tag[x] += tg;
    }
    inline void down(int x, int l, int r) {
        if(tag[x] == 0) return ;
        int mid = l+r>>1;
        pushtag(ls, tag[x], mid-l+1);
        pushtag(rs, tag[x], r-mid);
        tag[x] = 0;
    }
    inline void build(int x, int l, int r) {
        tag[x] = 0; 
        if(l == r) {
            mx[x] = mi[x] = s[x] = a[l];
            return ;
        }
        int mid = l+r>>1;
        build(ls, l, mid);
        build(rs, mid+1, r);
        up(x);
    }
    inline void edt(int x, int l, int r, int L, int R, int c) {
        if(L <= l && r <= R) {
            pushtag(x, c, r-l+1);
            return ;
        }
        down(x, l, r);
        int mid = l+r>>1;
        if(L <= mid) edt(ls, l, mid, L, R, c);
        if(R > mid) edt(rs, mid+1, r, L, R, c);
        up(x);
    }
    inline void div(int x, int l, int r, int L, int R, int d) {
        if(L <= l && r <= R) {
            ll A, B;
            if(mi[x] < 0) A = (mi[x] - d + 1) / d;
            else A = mi[x] / d;
            if(mx[x] < 0) B = (mx[x] - d + 1) / d;
            else B = mx[x] / d;
            if(mi[x] - A == mx[x] - B) {
                pushtag(x, A - mi[x], r-l+1);
                return ;
            }
        }
        down(x, l, r); 
        int mid = l+r>>1;
        if(L <= mid) div(ls, l, mid, L, R, d);
        if(R > mid) div(rs, mid+1, r, L, R, d);
        up(x);
    }
    inline ll sum(int x, int l, int r, int L, int R) {
        if(L <= l && r <= R) return s[x];
        down(x, l, r); 
        int mid = l+r>>1;
        ll ret = 0;
        if(L <= mid) ret += sum(ls, l, mid, L, R);
        if(R > mid) ret += sum(rs, mid+1, r, L, R);
        return ret;
    }
    inline ll gmin(int x, int l, int r, int L, int R) {
        if(L <= l && r <= R) return mi[x];
        down(x, l, r);
        int mid = l+r>>1;
        ll ret = 1e18;
        if(L <= mid) ret = min(ret, gmin(ls, l, mid, L, R));
        if(R > mid) ret = min(ret, gmin(rs, mid+1, r, L, R));
        return ret;
    }
}T;

int main() {
    int Q, opt, l, r, x;
    cin >> n >> Q;
    for (int i=1; i<=n; ++i) scanf("%d", a+i);
    T.build(1, 1, n);
    while(Q--) {
         scanf("%d%d%d", &opt, &l, &r); ++l, ++r;
        if(opt == 1) {
            scanf("%d", &x);
            T.edt(1, 1, n, l, r, x);
        } else if(opt == 2) {
            scanf("%d", &x);
            T.div(1, 1, n, l, r, x);
        } else if(opt == 3) printf("%lld\n", T.gmin(1, 1, n, l, r));
        else printf("%lld\n", T.sum(1, 1, n, l, r)); 
    }
    return 0;
}
View Code

 

loj6029 「雅礼集训 2017 Day1」市场

标签:div   targe   pen   get   fine   nbsp   gis   max   线段树   

原文地址:http://www.cnblogs.com/galaxies/p/loj6029.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!