zoukankan      html  css  js  c++  java
  • BZOJ1500: [NOI2005]维修数列

    妈呀,写的我心态崩了,注意以下几点:

    1.标记下放时应该立即更新子节点,才能pushup更新当前结点(此时实际上在当前结点的标记已经使用过了)。

    2.最好类似线段树的建树方法,否则容易RE。

    3.写个回收。

    4.我这splay写的是菜出狗屎了,在rotate里面pushdown,妈呀,就是因为没注意第一点,而且常数贼大,虽然可以过。

    5.其他就是加两个结点0,n+1,好处理就行了。

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <bitset>
    #include <stack>
    #include <set>
    #include <map>
    #include <list>
    #include <assert.h>
    using namespace std;
    #define e exp(1.0)
    typedef long long ll;
    #define MAXN 500005
    #define mod 100000007
    #define INF 1000000000
    #define fe(i,st,en) for(i = (st);i <= (en);++i)
    #define fne(i,st,en) for(i = (st);i < (en);++i)
    #define ri register int
    #define db double
    int n,b[MAXN];
    struct Splay {
        int a[MAXN], sz[MAXN], s[MAXN], lazy[MAXN],rev[MAXN], son[MAXN][2],lma[MAXN],rma[MAXN], ma[MAXN], fa[MAXN], root;
        int sta[MAXN], coll[MAXN], coll_top, _sz;
        void pushup(int o) {//o后代的信息修改后调用
            s[o] = a[o], sz[o] = 1;
            s[o] += s[son[o][0]], sz[o] += sz[son[o][0]];
            s[o] += s[son[o][1]], sz[o] += sz[son[o][1]];
            lma[o] = max(0, max(s[son[o][0]] + a[o] + lma[son[o][1]], lma[son[o][0]]));//该点表示的的区间前缀最大和
            rma[o] = max(0, max(s[son[o][1]] + a[o] + rma[son[o][0]], rma[son[o][1]]));//该点表示的的区间后缀最大和
            ma[o] = max(lma[son[o][1]]+rma[son[o][0]]+a[o], max(ma[son[o][0]], ma[son[o][1]]));
        }
        int build(int o,int l,int r,int v) {
            if (l > r) return 0;
            int mid = (l + r) >> 1;
            o = newnode(o, v, b[mid]);
            build(o,l,mid-1,0);
            build(o, mid+1, r,1);
            pushup(o);
            return o;
        }
        void pushdown(int o) {//查找询问前调用
            if (rev[o]) {
                swap(son[o][0], son[o][1]);
                swap(lma[o], rma[o]);
                if (son[o][0]) rev[son[o][0]] ^= 1;
                if (son[o][1]) rev[son[o][1]] ^= 1;
                rev[o] = 0;
            }
            if (lazy[o] != -INF) {
                a[o] = lazy[o], s[o] = lazy[o] * sz[o], ma[o] = max(lazy[o], lazy[o] * sz[o]);//lazy为负则max为lazy[o],否则为lazy[o]*sz[o]
                if (lazy[o] < 0) lma[o] = rma[o] = 0;
                else lma[o] = rma[o] = ma[o];
                if (son[o][0]) lazy[son[o][0]] = lazy[o];
                if (son[o][1]) lazy[son[o][1]] = lazy[o];
                lazy[o] = -INF;
            }
        }
        void change(int o, int fo, int v) {
            son[fo][v] = o, fa[o] = fo;
        }
        int newnode(int fo,int v,int x) {
            int o;
            if (coll_top) o = coll[coll_top--];
            else o = _sz++;
            son[o][0] = son[o][1] = rev[o] = 0, sz[o] = 1, lazy[o] = -INF, ma[o] = s[o] = a[o] = x;
            if (x > 0) lma[o] = rma[o] = x;
            else lma[o] = rma[o] = 0;
            change(o, fo, v);
            return o;
        }
        int isright(int o, int fo) {
            return son[fo][1] == o;
        }
        void rotate(int o) {
            int f = fa[o], g = fa[f], v = isright(o, f);
            change(o, g, isright(f, g));
            if (root == f) root = o;
            change(son[o][v ^ 1], f, v);
            change(f, o, v ^ 1);
            pushdown(son[f][0]),pushdown(son[f][1]),pushup(f);
        }
        void splay(int o,int fo) {
            while (fa[o] != fo) {
                int f = fa[o], g = fa[f];
                if (g != fo) (isright(o, f) ^ isright(f, g)) ? rotate(o) : rotate(f);
                rotate(o);
            }
            pushdown(son[o][0]), pushdown(son[o][1]);
            pushup(o);
        }
        int findpos(int o,int pos) {//找pos对应结点的过程中,该结点o和root之间的结点均调用pushdown,可能这个结点,结果死循环!
             pushdown(o);//更新翻转标记
            if (sz[son[o][0]] + 1 == pos) return o;
            if (sz[son[o][0]] >= pos) return findpos(son[o][0], pos);
            return findpos(son[o][1], pos-sz[son[o][0]]-1);
        }
        void insert(int pos,int tot) {
            splay(findpos(root, pos + 1), 0);
            splay(findpos(root, pos + 2), root);//r翻转到root右儿子
            for (ri i = 1; i <= tot; ++i) scanf("%d", b + i);
            int o = build(0, 1, tot, 0);
            change(o, son[root][1], 0);
            pushup(son[root][1]);
            pushup(root);
            n += tot;
        }
        void del(int pos, int tot) {
            splay(findpos(root, pos),0);//l-1翻转到root
            splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子
            int o = son[son[root][1]][0], top = 0;
            sta[++top] = o;
            while (top) {
                int t = sta[top--];
                coll[++coll_top] = t;
                if (son[t][0]) sta[++top] = son[t][0];
                if (son[t][1]) sta[++top] = son[t][1];
            }
            son[son[root][1]][0] = 0;
            pushup(son[root][1]);
            pushup(root);
            n -= tot;
        }
        void update(int pos, int tot, int x) {
            splay(findpos(root, pos), 0);//l-1翻转到root
            splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子
            lazy[son[son[root][1]][0]] = x;
            pushdown(son[son[root][1]][0]);
            pushup(son[root][1]);
            pushup(root);//把lazy pushdown后更新root和root的右儿子信息
        }
        void reverse(int pos, int tot) {
            splay(findpos(root, pos), 0);//l-1翻转到root
            splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子
            rev[son[son[root][1]][0]] ^= 1;//翻转会改变祖辈信息
            pushdown(son[son[root][1]][0]);
            pushup(son[root][1]), pushup(root);//
        }
        int querySum(int pos, int tot) {
            splay(findpos(root, pos), 0);//l-1翻转到root
            splay(findpos(root, pos + tot + 1), root);//r+1翻转到root右儿子
            return s[son[son[root][1]][0]];
        }
        int queryMax() {
            splay(findpos(root, 1), 0);//l-1翻转到root
            splay(findpos(root, n+2), root);//r+1翻转到root右儿子
            return ma[son[son[root][1]][0]];
        }
    }T;
    int main() {
        //freopen("C:\Users\Administrator\Desktop\input.in", "r", stdin);
        //cout << (1 << 30) - 1 << endl;
        int m, x, p, k;
        char s[20];
        ri i;
        scanf("%d%d", &n, &m);
        fe(i, 1, n) scanf("%d", b+i);
        b[0] = b[n + 1] = T.ma[0] = T.a[0] = T.lazy[0] = -INF;
        T._sz = 1, T.root = 1;
        T.build(0,0,n+1,0);
        //cout <<"T._sz:"<< T._sz << endl;
        fe(i, 1, m) {
            scanf("%s", s);
            if (s[0] == 'I') {
                scanf("%d%d", &p, &k);
                T.insert(p, k);
            }
            else if (s[0] == 'D') scanf("%d%d", &p, &k),T.del(p, k);
            else if (s[0] == 'R') scanf("%d%d", &p, &k),T.reverse(p, k);
            else if (s[0] == 'G') scanf("%d%d", &p, &k),printf("%d
    ", T.querySum(p, k));
            else if(s[2] == 'K') scanf("%d%d%d", &p, &k,&x),T.update(p, k, x);
            else printf("%d
    ", T.queryMax());
        }
        return 0;
    }
  • 相关阅读:
    提醒你一下, 你真的很垃圾, 创建一个maven 的web 项目都忘记了
    java web 项目中基础技术
    java 构造函数
    分布式简介
    RabbitMq 深入了解
    JS正则表达式验证数字非常全
    mui返回上个页面并刷新数据
    Windows环境下IOS APP打包上传AppStore详细流程
    crontab 详细用法 定时任务
    Linux epoll 源码注释
  • 原文地址:https://www.cnblogs.com/zhuiyicc/p/10947266.html
Copyright © 2011-2022 走看看