uva 12657
2015-09-27 10:21
405 查看
原题
本来没注意到M,N的规模, 用的STL的list, 后来发现找元素的时候实在太慢了( algorithm的find是顺序查找 )
然后看了答案, 发现可以用两个辅助数组 Left, Right来存每个元素的左右结点, 这样就不用一个个去查找出来再交换了,
这也是一种极简的实现双向链表的方法,
在比赛中往往没有时间写完一个数据结构的所有操作, STL效率又不够快时, 应该自己写一些简化的数据结构的操作
像这样用两个数组存储左右结点就是非常简洁快速的双向链表的结构,
还有就是定一个函数Link来简化链表的连接操作, 使得程序的思路清晰了很多
牢记!
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <list>
#include <cassert>
#include <iomanip>
#define CHECK
using namespace std;
const int MAXN = 100000 + 1;
const int BASE = 100000000;
typedef long long LL;
/*
uva 12657
关键 : 用两个辅助数组Left, Right实现简化双向链表
*/
//list<int> L;
//list<int>::iterator it1,it2,tmp;
int Left[MAXN], Right[MAXN]; // 简化双向链表结构
void Link(int L,int R){ // 【关键】 构造一个连接的函数,使算法更清晰
Left[R] = L;
Right[L] = R;
}
int main(){
int Case = 0, M, N;
int i,j,k,l1,r1,l2,r2;
while( scanf("%d %d",&N,&M)!=EOF && Case<10 ){
memset(Left,0,sizeof(Left));
memset(Right,0,sizeof(Right));
for(int m=0; m<=N; m++){
Link(m,m+1);
}
bool isReverse = false;
while( M-- ){
cin >> i;
if( i<4 ){
cin >> j >> k;
l1 = Left[j];
r1 = Right[j];
l2 = Left[k];
r2 = Right[k];
// it1 = find(L.begin(),L.end(),j); //
// it2 = find(L.begin(),L.end(),k); // 顺序查找, 过于费时, 不可行
if( i<3 && isReverse ) i = 3 - i;
switch( i ){
case 1: if( Left[k]==j ) break;
Link(l1,r1);
Link(l2,j);
Link(j,k);
break;
case 2: if( Left[j]==k ) break;
Link(l1,r1);
Link(j,r2);
Link(k,j);
break;
case 3: if( Left[j]==k ){
Link(l2,j);
Link(k,r1);
Link(j,k);
}else if( Left[k]==j ){
Link(l1,k);
Link(j,r2);
Link(k,j);
}else{
Link(l1,k);
Link(k,r1);
Link(l2,j);
Link(j,r2);
}
break;
}
}else if( i==4 ){
isReverse ^= true;
}
/*
#ifdef CHECK
cout << "Left : " << endl;
for(int i=0; i<=N; i++){
cout << Left[i] << " ";
}
cout << endl << "Right : " << endl;
for(int i=0; i<=N; i++){
cout << Right[i] << " ";
}
#else
int ptr = Right[0];
while( ptr<=N ){
cout << ptr << " ";
ptr = Right[ptr];
}
cout << endl;
ptr = Left[N+1];
while( ptr>0 ){
cout << ptr << " ";
ptr = Left[ptr];
}
#endif
cout << endl;
*/
}
LL sum = 0;
int ptr = Right[0];
for(int cnt=1; cnt<=N; cnt++){
if( cnt & 1 ){
sum += ptr;
// cout << ptr << " ";
}
ptr = Right[ptr];
}
if( isReverse && ( N%2==0 ) ) sum = (long long)N*(N+1)/2 - sum;
printf("Case %d: %lld\n",++Case,sum);
}
return 0;
}
本来没注意到M,N的规模, 用的STL的list, 后来发现找元素的时候实在太慢了( algorithm的find是顺序查找 )
然后看了答案, 发现可以用两个辅助数组 Left, Right来存每个元素的左右结点, 这样就不用一个个去查找出来再交换了,
这也是一种极简的实现双向链表的方法,
在比赛中往往没有时间写完一个数据结构的所有操作, STL效率又不够快时, 应该自己写一些简化的数据结构的操作
像这样用两个数组存储左右结点就是非常简洁快速的双向链表的结构,
还有就是定一个函数Link来简化链表的连接操作, 使得程序的思路清晰了很多
牢记!
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <list>
#include <cassert>
#include <iomanip>
#define CHECK
using namespace std;
const int MAXN = 100000 + 1;
const int BASE = 100000000;
typedef long long LL;
/*
uva 12657
关键 : 用两个辅助数组Left, Right实现简化双向链表
*/
//list<int> L;
//list<int>::iterator it1,it2,tmp;
int Left[MAXN], Right[MAXN]; // 简化双向链表结构
void Link(int L,int R){ // 【关键】 构造一个连接的函数,使算法更清晰
Left[R] = L;
Right[L] = R;
}
int main(){
int Case = 0, M, N;
int i,j,k,l1,r1,l2,r2;
while( scanf("%d %d",&N,&M)!=EOF && Case<10 ){
memset(Left,0,sizeof(Left));
memset(Right,0,sizeof(Right));
for(int m=0; m<=N; m++){
Link(m,m+1);
}
bool isReverse = false;
while( M-- ){
cin >> i;
if( i<4 ){
cin >> j >> k;
l1 = Left[j];
r1 = Right[j];
l2 = Left[k];
r2 = Right[k];
// it1 = find(L.begin(),L.end(),j); //
// it2 = find(L.begin(),L.end(),k); // 顺序查找, 过于费时, 不可行
if( i<3 && isReverse ) i = 3 - i;
switch( i ){
case 1: if( Left[k]==j ) break;
Link(l1,r1);
Link(l2,j);
Link(j,k);
break;
case 2: if( Left[j]==k ) break;
Link(l1,r1);
Link(j,r2);
Link(k,j);
break;
case 3: if( Left[j]==k ){
Link(l2,j);
Link(k,r1);
Link(j,k);
}else if( Left[k]==j ){
Link(l1,k);
Link(j,r2);
Link(k,j);
}else{
Link(l1,k);
Link(k,r1);
Link(l2,j);
Link(j,r2);
}
break;
}
}else if( i==4 ){
isReverse ^= true;
}
/*
#ifdef CHECK
cout << "Left : " << endl;
for(int i=0; i<=N; i++){
cout << Left[i] << " ";
}
cout << endl << "Right : " << endl;
for(int i=0; i<=N; i++){
cout << Right[i] << " ";
}
#else
int ptr = Right[0];
while( ptr<=N ){
cout << ptr << " ";
ptr = Right[ptr];
}
cout << endl;
ptr = Left[N+1];
while( ptr>0 ){
cout << ptr << " ";
ptr = Left[ptr];
}
#endif
cout << endl;
*/
}
LL sum = 0;
int ptr = Right[0];
for(int cnt=1; cnt<=N; cnt++){
if( cnt & 1 ){
sum += ptr;
// cout << ptr << " ";
}
ptr = Right[ptr];
}
if( isReverse && ( N%2==0 ) ) sum = (long long)N*(N+1)/2 - sum;
printf("Case %d: %lld\n",++Case,sum);
}
return 0;
}
相关文章推荐
- HDU 5475:An easy problem 这题也能用线段树做???
- HDU 5475:An easy problem 这题也能用线段树做???
- jenkins插件开发
- 学习笔记--linq链接数据库的几种方法
- java实战
- POJ 3126 Prime Path(BFS 数字处理)
- Android sdk 搭建
- HDU 1058 Humble Numbers
- win8.1镜像制作
- 获取一个数二进制序列中所有的偶数位和奇数位,分别输出二进制序列
- 580A
- stl string常用函数
- webvtt字幕转srt字幕方法
- Android 开发中的日常积累
- 在机器学习中用到了各式各样的距离
- Printk打印优先级设定
- 宁波金鸟服饰有限公司举行公司化运作第二阶段总结表彰大会
- OBPS开发平台——导入功能vb代码解析
- Seoul 2007 Meteor 流星 ,LA 3905
- 数据库相同版本的数据文件导入时出错