UVa 12657- Boxes in a Line

解题思路:
刚开始想的是直接用STL的list直接模拟,结果写了一发,很无奈,超时了,因此必须自己用数组模拟双向链表进行模拟,因此STL慎用,虽然好用方便但是对于有的题时间性能要求比较高,STL就成了瓶颈。。。

先给出一个连接两个节点的函数:
void link(int L, int R) {
right[L] = R; left[R] = L;
}
有了这个代码,可以先记录好操作之前X和Y两边的结点,然后用link函数按照某种顺序把它们连起来。操作4比较特殊,为了避免一次修改所有元素的指针,此处增加一个标记inv,inv=0表示没有执行过操作4(如果inv=1时再执行一次操作4,则inv变为0)。这样,当操作op为1和2且inv=1时,只需把op变成3-op(注意操作3不受inv影响)即可。最终输出时要根据inv的值进行不同处理。因为题目要求计算所有奇数位置的盒子编号之和,因此如果最终inv=1并且盒子总个数为奇数的话,那么反转对于本题的计算结果是没有影响的,因为以前位于奇数位置的现在还在奇数位置,只有当inv=1并且盒子总个数为偶数时计算结果才会与上面计算的ans不同,最终的ans=(LL)n*(n+1)/2-ans.

注意:如果ans定义的是long long,那么输出格式必须是%lld,不能使%I64d,否则会wa,别问我为什么,UVa上就是如此,我就因为这个wa了好多发,坑哭了,不信你试试!!!

贴代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <list>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define PI acos(-1.0)
#define seed 31//131,1313
#define MAXV 50010
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int maxn = 100000 + 10;
int Right[maxn],Left[maxn];
void link(int L,int R){
  Right[L]=R;
  Left[R]=L;
}
int main(){
  int n,m,cnt=1;
  while(scanf("%d%d",&n,&m)!=EOF){
     for(int i=1; i<=n; i++) {
         Left[i]=i-1;
         Right[i]=(i+1)%(n+1);
      }
    Right[0]=1;
    Left[0]=n;
    int op,x,y,inv=0;
    while(m--){
     scanf("%d",&op);
     if(op==4) inv=!inv;
     else{
        scanf("%d%d",&x,&y);
        if(op==3&&Right[y]==x) swap(x,y);
        if(op!=3&&inv) op=3-op;
        if((op==1&&x==Left[y])||(op==2&&x==Right[y])) continue;
        int lx=Left[x],rx= Right[x],ly=Left[y],ry=Right[y];
        if(op==1){
            link(lx,rx);
            link(ly,x);
            link(x,y);
        }
        else if(op==2){
            link(lx,rx);
            link(y,x);
            link(x,ry);
        }
        else if(op==3){
            if(Right[x]==y){
                link(lx,y);
                link(y,x);
                link(x,ry);
            }
            else{
                link(lx,y);
                link(y,rx);
                link(ly,x);
                link(x,ry);
            }
        }
       }
      }
      int b=0;
      LL ans=0;
      for(int i=1;i<=n;i++){
        b=Right[b];
        if(i%2) ans+=b;
      }
      if(inv&&n%2==0){
        ans=(LL)n*(n+1)/2-ans;
      }
      printf("Case %d: %lld\n",cnt++,ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值