[hdu5316]线段树

题意:给一个array,有两种操作,(1)修改某一个位置的值,(2)询问区间[L,R]内的最大子段和,其中子段需满足相邻两个数的位置的奇偶性不同

思路:假设对于询问操作没有奇偶性的限制,那么记录区间的最大子段和就可以通过合并区间得到答案了。加上奇偶性的限制后,记录的信息必须更加具体,需要把子段的端点的奇偶性加进去,也就是说一个区间需要记录4个值, 分别是奇奇,奇偶,偶偶,偶奇,然后同样可以通过合并区间来得到答案。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

/* ******************************************************************************** */

#include <iostream>                                                                 //

#include <cstdio>                                                                   //

#include <cmath>                                                                    //

#include <cstdlib>                                                                  //

#include <cstring>                                                                  //

#include <vector>                                                                   //

#include <ctime>                                                                    //

#include <deque>                                                                    //

#include <queue>                                                                    //

#include <algorithm>                                                                //

using namespace std;                                                                //

                                                                                    //

#define pb push_back                                                                //

#define mp make_pair                                                                //

#define X first                                                                     //

#define Y second                                                                    //

#define all(a) (a).begin(), (a).end()                                               //

#define foreach(i, a) for (typeof(a.begin()) it = a.begin(); it != a.end(); it ++)  //

                                                                                    //

void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}    //

void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>                    //

void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;          //

while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>      //

void print(const T t){cout<<t<<endl;}template<typename F,typename...R>              //

void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>   //

void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}   //

                                                                                    //

typedef pair<intint> pii;                                                         //

typedef long long ll;                                                               //

typedef unsigned long long ull;                                                     //

                                                                                    //

/* -------------------------------------------------------------------------------- */

                                                                                    //

template<typename T>bool umax(T &a, const T &b) {

    return a >= b? false : (a = b, true);

}

#define lson l, m, rt << 1

#define rson m + 1, r, rt << 1 | 1

const ll inf = (ll)1e18;

const int maxn = 1e5 + 7;

struct SegTree {

private:

    struct Node {

        ll a[4];

    };

    Node tree[maxn << 2];

    int n;

    bool chk(int i, int j) {

        return (i & 1) ^ (j >> 1);

    }

    int get(int i, int j) {

        return (i & 2) | (j & 1);

    }

    Node merge(const Node &nl, const Node &nr) {

        Node ans;

        for (int i = 0; i < 4; i ++) {

            ans.a[i] = nl.a[i];

            umax(ans.a[i], nr.a[i]);

        }

        for (int i = 0; i < 4; i ++) {

            for (int j = 0; j < 4; j ++) {

                if (chk(i, j)) {

                    umax(ans.a[get(i, j)], nl.a[i] + nr.a[j]);

                }

            }

        }

        return ans;

    }

    void build(int l, int r, int rt) {

        if (l == r) {

            int x;

            RI(x);

            int buf = (l & 1) << 1 | (l & 1);

            for (int i = 0; i < 4; i ++) tree[rt].a[i] = i == buf? x : -inf;

            return ;

        }

        int m = (l + r) >> 1;

        build(lson);

        build(rson);

        tree[rt] = merge(tree[rt << 1], tree[rt << 1 | 1]);

    }

    void update(int p, int x, int l, int r, int rt) {

        if (l == r) {

            tree[rt].a[(p & 1) << 1 | (p & 1)] = x;

            return ;

        }

        int m = (l + r) >> 1;

        if (p <= m) update(p, x, lson);

        else update(p, x, rson);

        tree[rt] = merge(tree[rt << 1], tree[rt << 1 | 1]);

    }

    Node query(int L, int R, int l, int r, int rt) {

        if (L <= l && r <= R) return tree[rt];

        int m = (l + r) >> 1;

        if (R <= m) return query(L, R, lson);

        if (L > m) return query(L, R, rson);

        return merge(query(L, R, lson), query(L, R, rson));

    }

public:

    void build(int nn) { n = nn; build(1, n, 1); }

    void update(int p, int x) { update(p, x, 1, n, 1); }

    ll query(int l, int r) {

        Node buf = query(l, r, 1, n, 1);

        ll ans = buf.a[0];

        for (int i = 1; i < 4; i ++) umax(ans, buf.a[i]);

        return ans;

    }

};

SegTree st;

int main() {

#ifndef ONLINE_JUDGE

    freopen("in.txt""r", stdin);

#endif // ONLINE_JUDGE

    int T;

    cin >> T;

    while (T --) {

        int n, m;

        RI(n, m);

        st.build(n);

        for (int i = 0; i < m; i ++) {

            int t, a, b;

            RI(t, a, b);

            if (t) st.update(a, b);

            else printf("%I64d\n", st.query(a, b));

        }

    }

    return 0;                                                                       //

}                                                                                   //

                                                                                    //

                                                                                    //

                                                                                    //

/* ******************************************************************************** */

时间: 2024-10-08 10:19:05

[hdu5316]线段树的相关文章

[线段树]hdu5316

题意: 给出两种操作,一种是求区间漂亮子序列的和的最大值,另一个就是给指定的点改变值. 题目中最重要的一句话:A beautiful subsequence is a subsequence that all the adjacent pairs of elves in the sequence have a different parity of position. 翻译:一个漂亮的子序列是指所有相邻的点在原序列中的奇偶性交替出现. 这就是问题的关键,否则还以为是裸线段树呢,多校题不会酱紫吧.

hdu5316(2015多校3)--Magician(线段树+dp)

题目链接:点击打开链接 题目大意:给出n个数,m次操作,有两种操作,0 l r 询问[l,r]内的一个序列最大和为多少,要求该序列的相邻的位置奇偶性不同,可以不连续:1 k x将第k个位置的数换位x 因为只要求奇偶性不同,所以一个序列的最大值有四种情况,偶数开始偶数结束,偶数开始奇数结束,奇数开始偶数奇数,奇数开始奇数结束.可以用一个数组表示,0表示偶数,1表示奇数,那么a[0][0],a[0][1],a[1][0],a[1][1]就能表示这四种情况了,查询[l,r]用线段树维护一下这四个值,注

hdu5316 Magician(线段树区间合并)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5316 题意:有n个精灵,每个精灵有一个能力值,有两种操作①改变某一个精灵的能力值②查询区间[L,R]里面位置奇偶相间的能力值的最大和. 分析:这题线段树区间合并可以做.每个节点保存4个信息:①以奇位置开始偶位置结束的奇偶序列最大和②以奇位置开始奇位置结束的奇偶序列最大和③以偶位置开始偶位置结束的奇偶序列最大和④以偶位置开始奇位置结束的奇偶序列最大和 合并的时候,以奇位置开始偶位置结束的奇偶序列最大和=m

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

bzoj1798: [Ahoi2009]Seq 维护序列seq 线段树

题目传送门 这道题就是线段树 先传乘法标记再传加法 #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int M=400010; LL read(){ LL ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击

luogu 1712 区间(线段树+尺取法)

题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭区间,然后线段树的每一个节点表示一个半开半闭区间. 接着我们注意到需要求最小的花费,且这个花费只与选择的区间集合中的最大长度和最小长度有关. 这意味着如果最大长度和最小长度一定,我们显然是需要把中间长度的区间尽量的选择进去使答案不会变的更劣. 不妨把区间按长度排序,枚举每个最小长度区间,然后最大区间

【BZOJ】1382: [Baltic2001]Mars Maps (线段树+扫描线)

1382: [Baltic2001]Mars Maps Time Limit: 5 Sec  Memory Limit: 64 MB Description 给出N个矩形,N<=10000.其坐标不超过10^9.求其面积并 Input 先给出一个数字N,代表有N个矩形. 接下来N行,每行四个数,代表矩形的坐标. Output 输出面积并 Sample Input 2 10 10 20 20 15 15 25 30 Sample Output 225 本以为是傻逼题,没想到不容易啊- 线段树+扫描