HDU 4453 Looploop (双向链表)

题意: 一个环状的序列,要求支持:

1,从光标开始k2个数增加x

2,从光标开始k1个数翻转

3,光标前插入一个数

4,删除光标位置的数

5,光标左/右移一位

6,询问光标位置的数

其中k1与k2为定值,且2<=k1<k2<=n,保证序列中元素个数始终不少于n。

解法: 虽然可以用各种平衡树搞定这题,但是题目给了那么多限制,不用简直浪费。

事实上用三个双向链表维护即可,第一个放元素1~k1,第二个放k1+1~k2,第三个放k2+1~n。维护一个1~k2的增量delta,一个1~k1的翻转标志rev,就变成一道近似模拟题了。

PS:STL的deque适用这题

/* Created Time: 2013年10月14日 星期一 16时15分08秒 */
#include <stdio.h>
int n,m,k1,k2,tot;
struct Node {
    Node *f,*b;
    int v;
}memo[2001000];
struct List {
    Node *head,*tail;
    List () {
        head = &memo[tot++];
        tail = &memo[tot++];
        head->b = tail;
        tail->f = head;
    }
    void insert(Node *a,Node *b,int x) {
        Node *c = &memo[tot++];
        c->v = x;
        a->b = b->f = c;
        c->f = a;
        c->b = b;
    }
    void remove(Node *c) {
        c->b->f = c->f;
        c->f->b = c->b;
    }
    void push_back(int x) {
        if (head->b==tail) insert(head,tail,x);
        else insert(tail->f,tail,x);
    }
    void push_front(int x) {
        if (head->b==tail) insert(head,tail,x);
        else insert(head,head->b,x);
    }
    int front() { return head->b->v; }
    int back() { return tail->f->v; }
    void pop_back() { remove(tail->f); }
    void pop_front() { remove(head->b); }
    int empty() { return head->b==tail; }
    void clear() { head->b = tail; tail->f = head; }
};
struct Data {
    List q1,q2,q3;
    int delta,rev;
    void init() {
        tot = 10;
        q1.clear(); q2.clear(); q3.clear();
        delta = 0;
        rev = 0;
    }
    void read() {
        int x;
        for (int i = 0; i < k1; i ++) {
            scanf("%d",&x);
            q1.push_back(x);
        }
        for (int i = k1; i < k2; i ++) {
            scanf("%d",&x);
            q2.push_back(x);
        }
        for (int i = k2; i < n; i ++) {
            scanf("%d",&x);
            q3.push_back(x);
        }
    }
    void add() {
        int x;
        scanf("%d",&x);
        delta += x;
    }
    void reverse() { rev ^= 1; }
    void insert() {
        int x,d;
        scanf("%d",&x);
        if (!rev) {
            d = q1.front(); q1.pop_front();
            q1.push_front(x-delta);
            q1.push_front(d);
            d = q1.back();
            q1.pop_back();
        } else {
            d = q1.back(); q1.pop_back();
            q1.push_back(x-delta);
            q1.push_back(d);
            d = q1.front();
            q1.pop_front();
        }
        q2.push_front(d);
        d = q2.back()+delta; q2.pop_back();
        q3.push_front(d);
    }
    void remove() {
        int d;
        if (!rev) {
            q1.pop_front();
            d = q2.front(); q2.pop_front();
            q1.push_back(d);
        } else {
            q1.pop_back();
            d = q2.front(); q2.pop_front();
            q1.push_front(d);
        }
        d = q3.front()-delta; q3.pop_front();
        q2.push_back(d);
    }
    void move() {
        int x,d;
        scanf("%d",&x);
        if (x==2) {
            if (!rev) {
                d = q1.front()+delta; q1.pop_front();
                q3.push_back(d);
                d = q2.front(); q2.pop_front();
                q1.push_back(d);
            } else {
                d = q1.back()+delta; q1.pop_back();
                q3.push_back(d);
                d = q2.front(); q2.pop_front();
                q1.push_front(d);
            }
            d = q3.front()-delta; q3.pop_front();
            q2.push_back(d);
        } else {
            if (!rev) {
                d = q1.back(); q1.pop_back();
                q2.push_front(d);
                d = q2.back()+delta; q2.pop_back();
                q3.push_front(d);
                d = q3.back()-delta; q3.pop_back();
                q1.push_front(d);
            } else {
                d = q1.front(); q1.pop_front();
                q2.push_front(d);
                d = q2.back()+delta; q2.pop_back();
                q3.push_front(d);
                d = q3.back()-delta; q3.pop_back();
                q1.push_back(d);
            }
        }
    }
    void query() {
        int ans;
        if (!rev) {
            ans = q1.front()+delta;
        } else {
            ans = q1.back()+delta;
        }
        printf("%d\n",ans);
    }
}nn;
int main() {
    char s[20];
    int ca = 0;
    while (~scanf("%d%d%d%d",&n,&m,&k1,&k2),n|m|k1|k2) {
        printf("Case #%d:\n",++ca);
        nn.init();
        nn.read();
        while (m--) {
            scanf("%s",s);
            if (s[0]=='a') nn.add();
            else if (s[0]=='r') nn.reverse();
            else if (s[0]=='i') nn.insert();
            else if (s[0]=='d') nn.remove();
            else if (s[0]=='m') nn.move();
            else nn.query();
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值