XTU1238 Segment Tree (線段樹·區間最值更新),xtu1238segment

來源:互聯網
上載者:User

XTU1238 Segment Tree (線段樹·區間最值更新),xtu1238segment

題意 對一個數組有四種操作

  • 1: 將區間[ l, r] 中的所有值都加上c
  • 2:將區間 [l, r] 中所有比c大的值改為c
  • 3:將區間 [l, r] 中所有比c小的值改為c
  • 4:輸出區間 [l, r] 中所有數的最小值和最大值

對每個操作4輸出對應最小值和最大值

基礎的線段樹 在湘潭卡了好久沒寫出來
線段樹維護三個值 區間最大值 maxv, 區間最小值minv, 區間增加的值add
操作1是很容易實現的 操作2和3比1要複雜些 初一想要對每個值單獨進行操作 這樣肯定會T的 畢竟那樣用線段樹就沒意義了 後來發現每次更新時對應區間包含的所有最大區間節點的maxv 和 minv是可以確定的

  • 操作2:maxv = min(maxv, c), minv = min(minv, c)
  • 操作3 : maxv = max(maxv, c), minv = max(minv, c)

然後知道了父區間的maxv,minv後 通過pashdown函數就可以在需要時再對子區間進行更新 因為子區間的所有值都是在父區間的minv和maxv之間 然後就看代碼吧

#include <bits/stdc++.h>#define lc p<<1, s, mid#define rc p<<1|1, mid+1, e#define mid ((s+e)>>1)using namespace std;const int N = 200005;int maxv[N * 4], minv[N * 4], add[N * 4];void pushup(int p){    maxv[p] = max(maxv[p << 1], maxv[p << 1 | 1]);    minv[p] = min(minv[p << 1], minv[p << 1 | 1]);}void pushdown(int p){    int l = p << 1;    int r = p << 1 | 1;    if(add[p])    {        add[l] += add[p];        add[r] += add[p];        minv[l] += add[p];        minv[r] += add[p];        maxv[l] += add[p];        maxv[r] += add[p];        add[p] = 0;    }    //子區間的所有值肯定都父區間的minv~maxv之間    minv[l] = max(minv[l], minv[p]);    minv[l] = min(minv[l], maxv[p]);    maxv[l] = max(maxv[l], minv[p]);    maxv[l] = min(maxv[l], maxv[p]);    minv[r] = max(minv[r], minv[p]);    minv[r] = min(minv[r], maxv[p]);    maxv[r] = max(maxv[r], minv[p]);    maxv[r] = min(maxv[r], maxv[p]);}void build(int p, int s, int e){    if(s == e)    {        scanf("%d", &maxv[p]);        minv[p] = maxv[p];        return;    }    build(lc);    build(rc);    pushup(p);}void update(int p, int s, int e, int l, int r, int v, int op){    if(s >= l && e <= r)    {        if(op == 1) //將[l,r]區間的所有值都加上v        {            add[p] += v;            minv[p] += v;            maxv[p] += v;        }        else if (op == 2)  //將[l,r]區間中所有大於v的值都改為v        {            maxv[p] = min(maxv[p], v);            minv[p] = min(minv[p], v);        }        else  //op = 3  將[l,r]區間中的所有小於v的值都改為v        {            maxv[p] = max(v, maxv[p]);            minv[p] = max(v, minv[p]);        }        return;    }    pushdown(p);    if(l <= mid) update(lc, l, r, v, op);    if(r > mid) update(rc, l, r, v, op);    pushup(p);}int query(int p, int s, int e, int l, int r, int op){    if(s == l && e == r)//op = 0 時查詢最小值  op = 1 時查詢最大值        return op ? maxv[p] : minv[p];    pushdown(p);    if(r <= mid) return query(lc, l, r, op);    if(l > mid) return query(rc, l, r, op);    if(op) return max(query(lc, l, mid, op), query(rc, mid + 1, r, op));    return min(query(lc, l, mid, op), query(rc, mid + 1, r, op));}int main(){    int T, n, q, l, r, op, c, ax, in;    scanf("%d", &T);    while(T--)    {        memset(add, 0, sizeof(add));        scanf("%d%d", &n, &q);        build(1, 1, n);        while(q--)        {            scanf("%d%d%d", &op, &l, &r);            if(op == 4)            {                ax = query(1, 1, n, l, r, 1);                in = query(1, 1, n, l, r, 0);                printf("%d %d\n", in, ax);            }            else            {                scanf("%d", &c);                update(1, 1, n, l, r, c, op);            }        }    }    return 0;}

Segment Tree

Problem Description:

A contest is not integrity without problems about data structure.
There is an array a[1],a[2],…,a[n]. And q questions of the following 4 types: • 1 l r c - Update a[k] with a[k]+c for all l≤k≤r
• 2 l r c - Update a[k] with min{a[k],c} for all l≤k≤r;
• 3 l r c - Update a[k] with max{a[k],c} for all l≤k≤r;
• 4 l r - Ask for min{a[k]:l≤k≤r} and max{a[k]:l≤k≤r}.

Input

The first line contains a integer T(no more than 5) which represents the number of test cases.

For each test case, the first line contains 2 integers n,q (1≤n,q≤200000).

The second line contains n integers a1,a2,…,an which indicates the initial values of the array (|ai|≤).

Each of the following q lines contains an integer t which denotes the type of i-th question. If t=1,2,3, 3 integers l,r,c follows. If t=4, 2 integers l,r follows. (1≤ti≤4,1≤li≤ri≤n)

If t=1, |ci|≤2000;

If t=2,3, |ci|≤10^9.

Output

For each question of type 4, output two integers denote the minimum and the maximum.

Sample Input

1
1 1
1
4 1 1

Sample Output

1 1

Source
XTU OnlineJudge

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.