UVa 12657- Boxes in a Line
2016-07-09 10:35
411 查看
解题思路:
刚开始想的是直接用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了好多发,坑哭了,不信你试试!!!
贴代码:
刚开始想的是直接用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); } }
相关文章推荐
- [C/C++]反转链表
- C#实现基于链表的内存记事本实例
- C#模拟链表数据结构的实例解析
- C语言实现带头结点的链表的创建、查找、插入、删除操作
- C++利用静态成员或类模板构建链表的方法讲解
- C++实现简单的学生管理系统
- Linux内核链表实现过程
- C++链表倒序实现方法
- C#通过链表实现队列的方法
- Node.js环境下JavaScript实现单链表与双链表结构
- C#实现的简单链表类实例
- 找出链表倒数第n个节点元素的二个方法
- Java数据结构之简单链表的定义与实现方法示例
- Java模拟有序链表数据结构的示例
- C语言单循环链表的表示与实现实例详解
- C++实现的链表类实例
- PHP小教程之实现链表
- PHP中模拟链表和链表的基本操作示例
- C语言双向链表的表示与实现实例详解
- js链表操作(实例讲解)