12657:Boxes in a Line

Boxes in a Line


反转链表时间开销太大,其实不需要反转只需要记录反转操作的次数即可,若最后次数为偶数,则从左往右加;若为奇数,则从右往左加。开始用指针链表超时,我以为是动态分配空间太慢,换数组链表还是超时,后来想到可能是忽略了特殊情况,看书后发现没有考虑到xy相邻的情况。。。还有就是如果不用判断到底从哪边加,因为计算机组成结构告诉我们分支结构的跳转太浪费时间,如果是翻转次数为奇数的话而且N为偶数的话拿总和去减奇数和即可。

version 1(指针链表,超时):

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 5;
int n,m;
struct node{
    int num;
    struct node *left;
    struct node *right;
};
node* d[maxn];
int main(){
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
    int kase = 0;
    while(scanf("%d %d",&n,&m) == 2){
        node* l = new node;
        node* r = new node;
        l->num = r->num = 0;
        node* a = l;
        for(int i = 1;i <= n;i++){
            node* t = new node;
            t->num = i;
            a->right = t;
            t->left = a;
            d[i] = a = t;
        }
        d[n]->right = r;
        r->left = d[n];
        int cmd,x,y;
        int mark = 0;
        while(m--){
            scanf("%d",&cmd);
            if(cmd == 1 || cmd == 2){
                scanf("%d %d",&x,&y);
                d[x]->left->right = d[x]->right;
                d[x]->right->left = d[x]->left;
            }
            if(cmd == 1){
                d[x]->right = d[y];
                d[x]->left = d[y]->left;
                d[y]->left->right = d[x];
                d[y]->left = d[x];
            }
            else if(cmd == 2){
                d[x]->left = d[y];
                d[x]->right = d[y]->right;
                d[y]->right->left = d[x];
                d[y]->right = d[x];
            }
            else if(cmd == 3){
                scanf("%d %d",&x,&y);
                node* t1 = d[x]->left;
                node* t2 = d[x]->right;
                d[x]->left = d[y]->left;
                d[y]->left->right = d[x];
                d[x]->right = d[y]->right;
                d[y]->right->left = d[x];
                d[y]->left = t1;
                t1->right = d[y];
                d[y]->right = t2;
                t2->left = d[y];
            }
            else mark = (mark+1)%2;
        }
        long long Sum = 0,odd = 1;
        if(!mark){
            while(l->right->num){
                if(odd++%2) Sum += l->right->num;
                l = l->right;
            }
        }
        else{
            while(r->left->num){
                if(odd++%2) Sum += r->left->num;
                r = r->left;
            }
        }
        printf("Case %d: %lld\n",++kase,Sum);
    }
    return 0;
}

version 2(数组链表,超时):

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 5;
int n,m;
int Left[maxn],Right[maxn];
void link(int l,int r){
    Left[r] = l;
    Right[l] = r;
}
int main(){
    // freopen("data.in","r",stdin);
    // freopen("data.out","w",stdout);
    int kase = 0;
    while(scanf("%d %d",&n,&m) == 2){
        int cmd,x,y;
        int mark = 0,l = 0,r = n+1;
        for(int i = 0;i <= n;i++){
            link(i,i+1);
        }
        while(m--){
            scanf("%d",&cmd);
            if(cmd == 1 || cmd == 2){
                scanf("%d %d",&x,&y);
                link(Left[x],Right[x]);
            }
            if(cmd == 1){
                link(Left[y],x);
                link(x,y);
            }
            else if(cmd == 2){
                link(x,Right[y]);
                link(y,x);
            }
            else if(cmd == 3){
                scanf("%d %d",&x,&y);
                int t1 = Left[x],t2 = Right[x];
                link(Left[y],x);
                link(x,Right[y]);
                link(t1,y);
                link(y,t2);
            }
            else mark = (mark+1)%2;
        }
        long long Sum = 0,odd = 1;
        if(mark){
            while(Left[r]){
                if(odd++%2) Sum += Left[r];
                r = Left[r];
            }
        }
        else{
            while(Right[l] != n+1){
                if(odd++%2) Sum += Right[l];
                l = Right[l];
            }
        }
        printf("Case %d: %lld\n",++kase,Sum);
    }
    return 0;
}
version 3(110ms):
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 5;
int n,m;
int Left[maxn],Right[maxn];
void link(int l,int r){
    Left[r] = l;
    Right[l] = r;
}
int main(){
    // freopen("data.in","r",stdin);
    // freopen("data.out","w",stdout);
    int kase = 0;
    while(scanf("%d %d",&n,&m) == 2){
        int cmd,x,y;
        int mark = 0,l = 0,r = n+1;
        for(int i = 0;i <= n;i++){
            link(i,i+1);
        }
        while(m--){
            scanf("%d",&cmd);
            if(cmd == 1 || cmd == 2){
                if(mark) cmd = 3 - cmd;
                scanf("%d %d",&x,&y);
            }
            if(cmd == 1){
                if(x == Left[y]) continue;
                link(Left[x],Right[x]);
                link(Left[y],x);
                link(x,y);
            }
            else if(cmd == 2){
                if(x == Right[y]) continue;
                link(Left[x],Right[x]);
                link(x,Right[y]);
                link(y,x);
            }
            else if(cmd == 3){
                scanf("%d %d",&x,&y);
                if(Right[y] == x) swap(x,y);
                int t1 = Left[x],t2 = Right[x];
                if(x == Left[y]){
                    link(x,Right[y]);
                    link(Left[x],y);
                    link(y,x);
                }
                else{
                    link(Left[y],x);
                    link(x,Right[y]);
                    link(t1,y);
                    link(y,t2);
                }
            }
            else mark = (mark+1)%2;
        }
        long long Sum = 0,odd = 1;
        if(mark){
            while(Left[r]){
                if(odd++%2) Sum += Left[r];
                r = Left[r];
            }
        }
        else{
            while(Right[l] != n+1){
                if(odd++%2) Sum += Right[l];
                l = Right[l];
            }
        }
        printf("Case %d: %lld\n",++kase,Sum);
    }
    return 0;
}

version 3(参考书上代码,80ms):

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 5;
int n,m;
int Left[maxn],Right[maxn];
void link(int l,int r){
    Left[r] = l;
    Right[l] = r;
}
int main(){
    // freopen("data.in","r",stdin);
    // freopen("data.out","w",stdout);
    int kase = 0;
    while(scanf("%d %d",&n,&m) == 2){
        int cmd,x,y;
        int mark = 0,l = 0;
        for(int i = 0;i <= n;i++){
            link(i,i+1);
        }
        while(m--){
            scanf("%d",&cmd);
            if(cmd == 4) mark = !mark;
            else{
                scanf("%d %d",&x,&y);
                if(cmd == 3 && Right[y] == x) swap(x,y);
                if(cmd != 3 && mark) cmd = 3 - cmd; //后两句要放后面。。
                if(cmd == 1 && Left[y] == x) continue;
                if(cmd == 2 && Right[y] == x) continue;
                int lx = Left[x],rx = Right[x],ly = Left[y],ry = Right[y];
                if(cmd == 1){
                    link(lx,rx); link(ly,x); link(x,y);
                }
                else if(cmd == 2){
                    link(lx,rx); link(x,ry); link(y,x);
                }
                else if(cmd == 3){
                    if(x == ly){
                        link(x,ry); link(lx,y); link(y,x);
                    }
                    else{
                        link(ly,x); link(x,ry); link(lx,y); link(y,rx);
                    }
                }
            }
        }
        long long Sum = 0,odd = 1;
        while(Right[l] != n+1){
            if(odd++%2) Sum += Right[l];
            l = Right[l];
        }
        if(mark && n%2 == 0) Sum = (long long)n*(n+1)/2 - Sum; //奇数的话两边数都一样的
        printf("Case %d: %lld\n",++kase,Sum);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值