uva 12657

原题

本来没注意到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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值