您的位置:首页 > 其它

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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: