这道题又是一道适合于练习链表的题目
这道题目中学到的东西有:
果然用数组代替链表编程要简单很多
具体原因可以把next New front看成是一体的,其实就相当于结构体的数组
双向链表的表示
如果想要逆转链表那么直接将next和front交换一下就可以了
memcopy的使用
链表的输出方式
但是很可惜的是,这样的方式在UVA看来是超时的,所以要想通过所有的case,那么就得使用刘汝佳的方式,将某一个操作记录下来。
下面先贴出超时的版本:
//这道题目刘汝佳的版本是要用一个flag来记录时间消耗比较大的操作,但是这种方法不一定能想到了,我还是先用数组的方式写一遍吧,看看效果怎样 //这种方式果然超时了,看来还是得用刘汝佳的方式啊 #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<ctime> using namespace std; int New[100000+5]; int Next[100000+5]; int front[100000+5]; int Copy[100000+5]; int num_node,num_comd; int start,last,kase = 0; void connect(int a,int b) { *(Next+a) = b; *(front+b) = a; } void pro(int x) { if(x == 1) { int a,b;//把a放在b的左面 scanf("%d%d",&a,&b); if(*(Next+a) == b) return; connect(*(front+a),*(Next+a)); connect(*(front+b),a); connect(a,b); } if(x == 2) { int a,b;//把a放在b的右面 scanf("%d%d",&a,&b); if(*(Next+b) == a) return; connect(*(front+a),*(Next+a)); connect(a,*(Next+b)); connect(b,a); } if(x == 3) { int a,b;//交换ab scanf("%d%d",&a,&b); if(*(Next+a) == b)//相邻 { connect(*(front+a),b); connect(a,*(Next+b)); connect(b,a); } else if(*(Next+b) == a) { connect(*(front+b),a); connect(b,*(Next+a)); connect(a,b); } else { int x1 = *(Next+b),x2 = *(front+b); connect(*(front+a),b); connect(b,*(Next+a)); connect(x2,a); connect(a,x1); } } if(x == 4) { int a = last; last = start; start= a; memcpy(Copy,front,sizeof(int)*(num_node+2)); memcpy(front,Next,sizeof(int)*(num_node+2)); memcpy(Next,Copy,sizeof(int)*(num_node+2)); } } void initial() { start = 0; last = num_node+1; for(int i = 0;i <= num_node+1;i++) { *(New+i) = i; *(Next+i) = i + 1; *(front+i) = i - 1; } //front[num_node+1]=num_node; *(Next+num_node+1)=0; //New[num_node+1]=num_node+1; *(front)=num_node+1; } void print_link() { for(int i = *(Next+start);*(New+i) != last;i = *(Next+i)) { printf("%d ",*(New+i)); } printf("\n"); } void print_ans() { long long sum = 0; for(int i = *(Next+start),num=1;*(New+i) != last;i = *(Next+i),num++) { if(num % 2 == 1) { sum = sum + *(New+i); } } cout<<"Case "<<++kase<<": "<<sum<<endl; } int main () { #ifdef local freopen("input.txt","r",stdin); freopen("output1.txt","w",stdout); #endif while(scanf("%d%d",&num_node,&num_comd)==2) { initial();//初始化数组 //print_link(); for(int i = 0;i < num_comd;i++) { int x; scanf("%d",&x); pro(x); //print_link(); } print_ans(); } printf("%lf",(double)clock()/CLOCKS_PER_SEC); return 0; }
再贴出我模仿刘汝佳的版本
//这道题目刘汝佳的版本是要用一个flag来记录时间消耗比较大的操作,但是这种方法不一定能想到了,我还是先用数组的方式写一遍吧,看看效果怎样 //这种方式果然超时了,看来还是得用刘汝佳的方式啊 #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<ctime> using namespace std; int New[100000+5]; int Next[100000+5]; int front[100000+5]; int num_node,num_comd; int start,last,kase = 0; int turn =0; void connect(int a,int b) { *(Next+a) = b; *(front+b) = a; } void pro(int x) { if(turn) { if(x==1) x=2; else if(x==2) x=1; } if(x == 1) { int a,b;//把a放在b的左面 scanf("%d%d",&a,&b); if(*(Next+a) == b) return; connect(*(front+a),*(Next+a)); connect(*(front+b),a); connect(a,b); } if(x == 2) { int a,b;//把a放在b的右面 scanf("%d%d",&a,&b); if(*(Next+b) == a) return; connect(*(front+a),*(Next+a)); connect(a,*(Next+b)); connect(b,a); } if(x == 3) { int a,b;//交换ab scanf("%d%d",&a,&b); if(*(Next+a) == b)//相邻 { connect(*(front+a),b); connect(a,*(Next+b)); connect(b,a); } else if(*(Next+b) == a) { connect(*(front+b),a); connect(b,*(Next+a)); connect(a,b); } else { int x1 = *(Next+b),x2 = *(front+b); connect(*(front+a),b); connect(b,*(Next+a)); connect(x2,a); connect(a,x1); } } if(x == 4) { turn=!turn; } } void initial() { start = 0; last = num_node+1; for(int i = 0;i <= num_node+1;i++) { *(New+i) = i; *(Next+i) = i + 1; *(front+i) = i - 1; } //front[num_node+1]=num_node; *(Next+num_node+1)=0; //New[num_node+1]=num_node+1; *(front)=num_node+1; } void print_link() { for(int i = *(Next+start);*(New+i) != last;i = *(Next+i)) { printf("%d ",*(New+i)); } printf("\n"); } void print_ans() { long long sum = 0; if(!turn||num_node%2==1) { for(int i = *(Next+start),num=1;*(New+i) != last;i = *(Next+i),num++) { if(num % 2 == 1) { sum = sum + *(New+i); } } } else { for(int i = *(Next+start),num=1;*(New+i) != last;i = *(Next+i),num++) { if(num % 2 == 0) { sum = sum + *(New+i); } } } cout<<"Case "<<++kase<<": "<<sum<<endl; } int main () { #ifdef local freopen("input.txt","r",stdin); freopen("output1.txt","w",stdout); #endif while(scanf("%d%d",&num_node,&num_comd)==2) { turn = 0; initial();//初始化数组 //print_link(); for(int i = 0;i < num_comd;i++) { int x; scanf("%d",&x); pro(x); //print_link(); } print_ans(); } //printf("%lf",(double)clock()/CLOCKS_PER_SEC); return 0; }
首先如果要使用这种方式,那么第一步应该做的是将上一个容易超时的写出来,成功之后再使用第二种,之后还需要对拍。
这道题犯过的错误是两个if写在了一起
以后绝对不能出现这种情况,两个if写在一起和if else 在想要实现的功能上是完全没有区别的。