Gorgeous Sequence(线段树)

Gorgeous Sequence

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 6946    Accepted Submission(s): 1784

Problem Description

There is a sequence a of length n. We use ai to denote the i-th element in this sequence. You should do the following three types of operations to this sequence.

0 x y t: For every x≤i≤y, we use min(ai,t) to replace the original ai‘s value.
1 x y: Print the maximum value of ai that x≤i≤y.
2 x y: Print the sum of ai that x≤i≤y.

Input

The first line of the input is a single integer T, indicating the number of testcases.

The first line contains two integers n and m denoting the length of the sequence and the number of operations.

The second line contains n separated integers a1,…,an (∀1≤i≤n,0≤ai<231).

Each of the following m lines represents one operation (1≤x≤y≤n,0≤t<231).

It is guaranteed that T=100, ∑n≤1000000, ∑m≤1000000.

Output

For every operation of type 1 or 2, print one line containing the answer to the corresponding query.

Sample Input

1
5 5
1 2 3 4 5
1 1 5
2 1 5
0 3 5 3
1 1 5
2 1 5

Sample Output

5
15
3
12

Hint

Please use efficient IO method

Author

XJZX

Source

2015 Multi-University Training Contest 2

Recommend

wange2014   |   We have carefully selected several similar problems for you:  6554 6553 6552 6551 6550

题意 :

有一个长度为n的序列a。我们用ai来表示这个序列中的第i个元素。您应该对这个序列执行以下三种类型的操作。

0 x y t:对于每一个x≤i≤y,我们用min(ai,t)替换原始ai的值。

1 x y:打印ai的最大值,即x≤i≤y。

2xy:输出x≤i≤y的ai之和。

输入

输入的第一行是一个整数T,表示测试用例的数量。

第一行包含两个整数n和m,表示序列的长度和操作的数量。

第二行包含n分离整数a1,…,一个(∀1≤≤n, 0≤ai < 231)。

以下m行每一行表示一个操作(1≤x≤y≤n,0≤t<231)。

保证T=100,∑n≤1000000,∑m≤1000000。

输出

对于类型1或2的每个操作,打印一行包含相应查询的答案。

题解:

c++代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
int a[maxn];
#define EF if(ch==EOF) return x;
// #define lc k<<1
// #define rc k<<1|1
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;EF;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct tree
{
    int l , r;
    int miax , maxx;
    ll sum;
    int set_lazy;
}t[maxn << 2];

// inline void push_up(int k){
//     // sum[k]=sum[lc]+sum[rc];
//     // mx[k]=max(mx[lc],mx[rc]);
//     // se[k]=max(se[lc],se[rc]);
//     // mc[k]=0;
//     // if(mx[lc]!=mx[rc]) se[k]=max(se[k],min(mx[lc],mx[rc]));
//     // if(mx[k]==mx[lc]) mc[k]+=mc[lc];
//     // if(mx[k]==mx[rc]) mc[k]+=mc[rc];
//     t[k].sum = t[lc].sum + t[rc].sum;
//     t[k].maxx = max(t[lc].maxx,t[rc].maxx);
//     t[k].miax = max(t[lc].miax,t[rc].miax);
//     t[k].set_lazy = 0;
//     if(t[lc].maxx != t[rc].maxx) t[k].miax = max(t[k].miax,min(t[lc].maxx,t[rc].maxx));
//     if(t[k].maxx == t[lc].maxx) t[k].set_lazy += t[lc].set_lazy;
//     if(t[k].maxx == t[rc].maxx) t[k].set_lazy += t[rc].set_lazy;

// }
inline void push_up(int rt){
    t[rt].sum = t[rt << 1].sum + t[rt << 1|1].sum;
   // t[rt].minn = min(t[rt << 1].minn,t[rt << 1|1].minn);
    t[rt].maxx = max(t[rt << 1].maxx,t[rt << 1|1].maxx);
    t[rt].miax = max(t[rt << 1].miax, t[rt << 1|1].miax);
    t[rt].set_lazy = 0;
    if(t[rt << 1].maxx != t[rt <<1|1].maxx) t[rt].miax = max(t[rt].miax,min(t[rt << 1].maxx , t[rt <<1|1].maxx));
    //打上标记,记录下标记个数
    if(t[rt].maxx == t[rt << 1].maxx) t[rt].set_lazy += t[rt << 1].set_lazy;
    if(t[rt].maxx == t[rt << 1|1].maxx) t[rt].set_lazy += t[rt << 1|1].set_lazy;
   // cout << t[rt].sum << " " << rt <<endl;
}

inline void dec_tag(int rt,int v){
    if(v >= t[rt].maxx) return;
    t[rt].sum += 1ll * (v - t[rt].maxx)*t[rt].set_lazy;
    t[rt].maxx = v;
}

inline void push_down(int rt){
    dec_tag(rt << 1,t[rt].maxx);
    dec_tag(rt << 1|1,t[rt].maxx);
}
  // inline void push_down(int rt) {
  //       if(t[rt].set_lazy) { ///if set_lazy add_lazy = 0
  //           t[rt<<1].set_lazy = t[rt].set_lazy;
  //           t[rt<<1].sum = (t[rt<<1].r - t[rt<<1].l + 1) * t[rt].set_lazy;
  //           t[rt<<1].maxx = t[rt].set_lazy;
  //           t[rt<<1].minn = t[rt].set_lazy;
  //           t[rt<<1|1].set_lazy = t[rt].set_lazy;
  //           t[rt<<1|1].sum = (t[rt<<1|1].r - t[rt<<1|1].l + 1) * t[rt].set_lazy;
  //           t[rt<<1|1].maxx = t[rt].set_lazy;
  //           t[rt<<1|1].minn = t[rt].set_lazy;
  //           //tre[rt].add_lazy = 0;
  //           //tre[rt<<1].add_lazy = tre[rt<<1|1].add_lazy = 0;
  //           t[rt].set_lazy = 0;
  //           return ;
  //       }
  //       // if(tre[rt].add_lazy) {
  //       //     tre[rt<<1].add_lazy += tre[rt].add_lazy;
  //       //     tre[rt<<1].sum += (tre[rt<<1].r - tre[rt<<1].l + 1) * tre[rt].add_lazy;
  //       //     tre[rt<<1].max += tre[rt].add_lazy;
  //       //     tre[rt<<1].min += tre[rt].add_lazy;
  //       //     tre[rt<<1|1].add_lazy += tre[rt].add_lazy;
  //       //     tre[rt<<1|1].sum += (tre[rt<<1|1].r - tre[rt<<1|1].l + 1) *
  //       //                         tre[rt].add_lazy;
  //       //     tre[rt<<1|1].max += tre[rt].add_lazy;
  //       //     tre[rt<<1|1].min += tre[rt].add_lazy;
  //       //     tre[rt].add_lazy = 0;
  //       // }
  //   }

void build(int rt,int l ,int r){
    t[rt].l = l, t[rt].r = r;
    //t[rt].set_lazy = 1;

    if(l == r){
        t[rt].sum =  t[rt].maxx = a[l];
        t[rt].miax = -1;
        t[rt].set_lazy = 1;
       // cout <<"nbb  " <<t[rt].sum << " "<<rt << endl;
        return;
    }
    int mid = (l + r) >> 1;
    build(rt <<1,l,mid);
    build(rt << 1|1,mid + 1,r);
    push_up(rt);
}

void up_date(int rt,int l,int r,int d){
    if(d >= t[rt].maxx) return;

    //push_down(rt);
    if(l <= t[rt].l && r >= t[rt].r && d > t[rt].miax){
     // t[rt].sum = (t[rt].r - t[rt].l + 1) * d;
     // t[rt].maxx = d;
     // t[rt].minn = d;
     // t[rt].set_lazy = d;
     dec_tag(rt,d);
     return;
 }
 push_down(rt);
 int mid = (t[rt].l + t[rt].r) >> 1;
 if(r <= mid) {
    up_date(rt<<1,l,r,d);
} else if(l > mid) {
    up_date(rt<<1|1,l,r,d);
} else {
    up_date(rt<<1,l,mid,d);
    up_date(rt<<1|1,mid+1,r,d);
}
push_up(rt);
}

 ll query_sum(int rt,int l,int r) { ///sum

    if(l <= t[rt].l && t[rt].r <= r) {
        return t[rt].sum;
    }
    push_down(rt);
    int mid = (t[rt].l + t[rt].r) >> 1;
    if(r <= mid) {
        return query_sum(rt<<1,l,r);
    } else if(l > mid) {
        return query_sum(rt<<1|1,l,r);
    } else {
        return query_sum(rt<<1,l,mid) + query_sum(rt<<1|1,mid+1,r);
    }
}

    int query_max(int rt,int l,int r) { ///max

       //cout << t[rt].maxx  << endl;
        if(l <= t[rt].l && t[rt].r <= r) {
            return t[rt].maxx;
        }
        push_down(rt);
        int mid = (t[rt].l + t[rt].r) >> 1;
        if(r <= mid) {
            return query_max(rt<<1,l,r);
        } else if(l > mid) {
            return query_max(rt<<1|1,l,r);
        } else {
            return max(query_max(rt<<1,l,mid), query_max(rt<<1|1,mid+1,r));
        }
    }
    // int query_min(int rt,int l,int r) { ///min
    //     push_down(rt);

    //     if(l <= t[rt].l && t[rt].r <= r) {
    //         return t[rt].minn;
    //     }
    //     int mid = (t[rt].l + t[rt].r) >> 1;
    //     if(r <= mid) {
    //         return query_min(rt<<1,l,r);
    //     } else if(l > mid) {
    //         return query_min(rt<<1|1,l,r);
    //     } else {
    //         return min(query_min(rt<<1,l,mid), query_min(rt<<1|1,mid+1,r));
    //     }
    // }

    int main(int argc, char const *argv[])
    {
        int t;
        //scanf("%d",&t);
        t = read();
        while(t--){
            int n , q;
            //scanf("%d%d",&n,&q);
            n = read(),q = read();
            for(int i = 1;i <= n; i++) //scanf("%d",&a[i]);
                a[i] = read();
            build(1,1,n);
   // //0 cout << 1;
   //  for(int i = 1;i <= n; i++){
   //      cout << t[i].maxx ;
   //  }
            while(q--){
                int a,b,c;
                //scanf("%d%d%d",&a,&b,&c);
                a = read() ,b = read() , c = read();
                if(a == 0){
                    int z;
                    //scanf("%d",&z);
                    z = read();

                    up_date(1,b,c,z);
                }
                else if(a == 1){
                    printf("%d\n",query_max(1,b,c));
                }
                else{
                    printf("%lld\n",query_sum(1,b,c));
                }
            }
        }
        return 0;
    }

原文地址:https://www.cnblogs.com/DWVictor/p/11195740.html

时间: 2024-11-09 06:18:09

Gorgeous Sequence(线段树)的相关文章

HDU 5306 Gorgeous Sequence[线段树区间最值操作]

Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2150    Accepted Submission(s): 594 Problem Description There is a sequence a of length n. We use ai to denote the i-th elemen

HDOJ 5306 Gorgeous Sequence 线段树

http://www.shuizilong.com/house/archives/hdu-5306-gorgeous-sequence/ Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 440    Accepted Submission(s): 87 Problem Description Th

【hdu5306】Gorgeous Sequence 线段树区间最值操作

题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y$ :求 $[x,y]$ 内所有数的和. 多组测试数据,$\sum n,\sum m\le 10^6$ 题解 线段树区间最值操作 对于线段树上的一个节点,维护对应区间的:最大值 $mx$ .最大值个数 $c$ 及严格次大值 $se$ .那么对于一次区间最小值操作: 如果 $t\ge mx$ ,则这个

hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

HDOJ 4893 Wow! Such Sequence! 线段树

http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:10万的区间,初始都为0,10万次操作,三种操作为单点修改,区间将每个数改成最近的斐波那契数,以及区间求和. 分析:用一个flag记录该段是否被改成斐波那契数,同时多维护一个sum1表示如果该段改成斐波那契数,区间和为多少.开始sum1为区间长度,之后在单点做了修改以后对其更新,需要的时候用其覆盖sum. 1 #include<cstdio> 2 #include<cstring>

HDU4893 Wow! Such Sequence! 线段树

题意:给你一个序列,其中有三种操作 1)位置为K 的数+ D 2)求 l-r 区间和 3)把 l-r 区间里面的所有数都变为理它最近的斐波纳契数 解题思路:这个题的区间更新其实可以在单点更新的时候就得出,为节点维护两个 和,一个是 斐波纳契和 一个是正常和 ,再看这个区间有没有被3覆盖,特判一下就行了. 解题代码: 1 // File Name: 1007.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月29日 星期二 12时49分33

hdu-4893-Wow! Such Sequence!-线段树【2014多校第三场-J】

题意:一个初始为0的数组,支持三种操作:1.向第k个数添加d,(|d| < 2^31);2.把[l, r]区间内的数字都换成与它最相近的Fibonacci数;3.询问[l, r]区间的和. 思路:初始化Fibonacci数组,longlong 类型内90个就够用了. 线段树区间查询,用lazy标记, sgt[]记录线段树各个节点的区间和, fib_num_sum[]记录与各个叶子节点当前值最接近的Fibonacci数,传递到区间fib_num_sum[]就是区间Fibonacci数的和. 操作1

2014多校3 Wow! Such Sequence!线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 这题实在是让人纠结啊--好久不写线段树的题了,因为这几天学伸展树,然后觉得线段树小case了.没想到栽在这题上了.尼玛-- 自己把自己给搞晕了--想复杂了,都不懂得预处理一下,唉--还得怒刷几十道啊!! #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #in

CF(438D) The Child and Sequence(线段树)

题意:对数列有三种操作: Print operation l,?r. Picks should write down the value of . Modulo operation l,?r,?x. Picks should perform assignment a[i]?=?a[i] mod x for each i (l?≤?i?≤?r). Set operation k,?x. Picks should set the value of a[k] to x (in other words