hdu 4699 2个栈维护 or 伸展树 (2013多校联合)

来源:互联网 发布:alex老帅哥淘宝店名 编辑:程序博客网 时间:2024/06/06 02:49

hdu 4699  Editor

题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求1到k位置的最大的前缀和。。

注意这里的k是在光标之前的,由于这个条件,所以这题又简单的2个栈维护可以解,如果没有这个条件,那么就要用伸展树了。

栈的解法叉姐的解题报告有,我这里说说伸展树的做法, 1.8MS卡过。

我们用cur表示光标在第几个数的右边,size表示数的总个数。

对于操作L: 没有移到最左边就cur--

对于操作R: 没有移到最右边就cur++

对于操作D: 把当前的第cur个位置的节点旋到根,再把第cur-1位置的节点旋到根的左边,令根的左右儿子分别为L,R

那么L一定没有右儿子,把L变为根, R变为L的右儿子。

对于操作I x:把当前的第cur个位置的节点旋到根,在根和根的右儿子之间插入一个新节点。

对于操作Q x:相当于询问1------x区间的最大前缀和。把第0个节点旋到根,把第x-1个节点旋到根的右边。

如何求最大前缀和, 维护一个sum[x]表示区间和,ans[x]表示在x为根的区间里的最大前缀和(注意至少要取一个数)。

伸展树:

#include <cstdio>#include <cstring>#include <algorithm>const int maxn = 1000006;const int inf  = 1e9+6;using namespace std;#define L ch[x][0]#define R ch[x][1]#define KT ch[ ch[root][1]][0]int cur, size;struct splaytree {    int sz[maxn], ch[maxn][2], pre[maxn];    int tot, root;    int sum[maxn], val[maxn], ans[maxn];    int sta[maxn], top;    void rotate(int &x, int f) {        int y = pre[x], z = pre[y];        ch[y][!f] = ch[x][f];        pre[ch[x][f]] = y;        pre[x] = pre[y];        if(z) ch[z][ch[z][1] == y] = x;        ch[x][f] = y;        pre[y] = x;        up(y);    }    void splay(int &x, int g) {        while(pre[x] != g) {            int y = pre[x], z = pre[y];            if(z == g) rotate(x, ch[y][0] == x);            else {                int f = (ch[z][0] == y);                ch[y][!f] == x ? rotate(y, f) : rotate(x, !f);                rotate(x, f);            }        }        if(!g) root = x;        up(x);    }    void rto(int k, int g) {        int x = root;        while(sz[L] != k) {            if(sz[L] > k) x = L;            else {                k -= sz[L]+1;                x = R;            }        }        splay(x, g);    }    void newNode(int &x, int v, int fa) {        if(top) x = sta[top--];        else x = ++tot;        sz[x] = 1;        pre[x] = fa;        L = R = 0;        sum[x] = ans[x] = val[x] = v;    }    void init() {        top = tot = 0;        cur = size = 0;        newNode(root, -inf, 0);        newNode(ch[root][1], -inf, root);    }    void insert(int k, int v) {        rto(k, 0);//debug();        int x;        newNode(x, v, root);        ch[x][1] = ch[root][1];        if(ch[x][1])pre[ch[x][1]] = x;        ch[root][1] = x;        up(x);        up(root);    }    void erase(int k) {        rto(k, 0);        rto(k-1, root);        sta[++top] = root;        int l = ch[root][0], r = ch[root][1];        root = l;        pre[l] = 0;        ch[l][1] = r;        if(r)pre[r] = l;        up(l);    }    void query(int k) {        rto(0, 0);        rto(k+1, root);        printf("%d\n", ans[KT]);    }    void up(int x) {        sz[x] = sz[L] + sz[R] + 1;        sum[x] = sum[L] + sum[R] + val[x];        if(!sz[L]) {            ans[x] = max(val[x], val[x]+ans[R]);        }        else {            ans[x] = max(ans[L], sum[L] + max(val[x], 0));            ans[x] = max(ans[x], sum[L]+ val[x]+max(0, ans[R]));        }    }    void print(int x) {        printf("node %d, left %d, right %d, pre %d, sum %d, ans %d, val %d\n", x, L, R, pre[x], sum[x], ans[x], val[x]);        if(L) print(L);        if(R) print(R);    }    void debug() {        printf("root = %d cur = %d size = %d\n", root, cur, size);        print(root);    }    void down(int x) {    }}spt;int main() {    int m, x;    char op[3];    while( ~scanf("%d", &m)) {        spt.init();        while(m--) {            scanf("%s", op);            if(op[0] == 'L') {                if(cur)cur--;            }            else if(op[0] == 'R') {                if(cur < size)cur++;            }            else if(op[0] == 'D') spt.erase(cur--), size--;            else {                scanf("%d", &x);                if(op[0] == 'I') spt.insert(cur++, x), size++;                else spt.query(x);            }        //    spt.debug();        }    }    return 0;}

栈维护:

#include <cstdio>#include <cstring>#include <stack>using namespace std;const int maxn = 1000006;int dp[maxn], sum[maxn], m, x;const int inf =  1e9+6;char op[3];int l[maxn], r[maxn], t1, t2;int main() {    while( ~scanf("%d", &m)) {        dp[0] = -inf;        t1 = t2 = 0;        while(m--) {            scanf("%s", op);            if(op[0] == 'I') {                scanf("%d", &x);                l[++t1] = x;                sum[t1] = sum[t1-1] + x;                dp[t1] = max(dp[t1-1], sum[t1]);            }            else if(op[0] == 'L') {                if(!t1) continue;                r[++t2] = l[t1--];            }            else if(op[0] == 'R') {                if(!t2) continue;                l[++t1] = r[t2--];                sum[t1] = sum[t1-1] + l[t1];                dp[t1] = max(dp[t1-1], sum[t1]);            }            else if(op[0] == 'D') t1--;            else {                scanf("%d", &x);                printf("%d\n", dp[x]);            }        }    }    return 0;}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果手机相机不对焦怎么办 苹果手机摄像头不能对焦了怎么办 闪电邮里面邮件太多怎么办 苹果手机和助理打不开怎么办 苹果我的世界打不开怎么办 ps试用7天到期了怎么办 皮肤锁不住水份怎么办 硫酸弄到皮肤上怎么办 直播时图像反看怎么办 快手直播权限被收回怎么办 快手直播权限被收回了怎么办 腾讯手游助手玩游戏卡怎么办 电脑直播视频打不开了怎么办 平板进水开不了机怎么办 苹果平板进水开不了机怎么办 苹果平板电脑进水了怎么办 电脑换主机以前的文件怎么办 货车卖了没过户怎么办 微交易出金不了怎么办 直播时出现央视影音客户端怎么办 qq账号暂时无法登录怎么办 饿了吃东西胃疼怎么办 早上不吃饭胃疼怎么办 孕晚期胃疼呕吐怎么办 胃疼了一晚上怎么办 微信视频图像倒立怎么办 ps链接图层锁定怎么办 慕课过时间了怎么办 异地恋又要考研怎么办 阴阳师手机绑定上限了怎么办 高考口令卡丢了怎么办 网易将军令换手机了怎么办 须弥bb有弱点土怎么办 战网密码忘记了怎么办 梦三账号忘了怎么办 快手手机号被注册了怎么办 快手该手机号已注册怎么办 手机号被别人注册了快手怎么办 快手显示手机号已注册怎么办 163的邮箱忘了怎么办 河长制账号密码忘了怎么办