一行盒子

题意理解:

给一行数字(给出个数,从小到大从做到右排列),经过一些变化后,输出其顺序排在奇数位置上的数的和。

一个n,表示n个数顺序排列(1-n);

一个m,表示每次变化;

接着m次变化操作:

1 、u x y,把x移动到y的左边(u=1);

2 、u x y,把x移动到y的右边(u=2);

3 、u x y,把x和y的位置调换(u=3);

4 、u,把序列翻转过来,方向调转;


思路解析:


这个题目,在省赛回来后A出来,把代码贴上来,一直心痛,就没有再碰过。今天来写完它,真的是一道伤口,害怕揭开后的疼痛,是整个心都痉挛。


最开始的时候,对map和set不够熟悉,看到里面的insert(iterator,x),以为可以把键插到中间,直接就做了。这和比赛前一直用STL有关系,非常依赖STL。后面真的按照这个思想敲了,等我花了将近半小时敲完的时候才发现,即使是insert还是改变不了map里面的重头到尾的插入顺序,整个思想是对的,但是,map的插入方式却直接击溃了整个精神,当时离比赛结束只有20分钟,直接与AC无缘。这构成了我ACM人生的一大遗憾。最终,由于本题没能A出来,与奖杯距离六步之遥。。。再也不要“深藏功与名”!!


谨以此告诫所有主攻STL的同僚,要不就别学,要学就一定要搞清楚所以然,不要重蹈我的覆辙。


ACM毁大学,AC毁一生!


后来听说用双向链表可以过,自己写了个裸链表。。。答案是没问题,一提交就看到了TLE。郁闷了一整天后发现最耗时的是寻找节点的find()函数。果断改良,用map记录每个节点的地址(指针),在链表初始化的时候就初始化map的键。对于每个要移动的节点,先从链表中删除;然后再新建节点,插入到链表,同时更新map【见代码一】;对于方向,只要记录改变的次数,在操作处理时改变目标节点就可以了;最后计算的时候,直接按照方向从链表头和链表尾逐个编立计数,当计数变量为奇数的时候,累加节点的值,输出累加变量的值即可。


后面突发奇想,干脆不删除节点,直接将拿出来的要改变位置的节点插入到指定节点后面即可,不用更新map,也不必新建和删除节点,可以节约时间。于是就写了【代码二】,改进后的程序运行时间节约了72ms。时间不多,但是,思路更简洁了。改进了冗余部分。


个人感想:

省赛后,一直耿耿于怀,很久没有与AC约会,代码也打得少。快一个月了,回来机房打代码,打了没几行,有种热泪盈眶的感觉。当手指在键盘跳动,心里就是别有一番滋味。突然就想到前段时间去电子电工基地帮忙打文件,有人说“打代码的人就是不一样,敲键盘的节奏就不同”。当时小有感触,但也没放在心上。现在手指在键盘上游走,有种舍不得离开的感觉,就像就别重逢的恋人。说不出的。。。

本来就想着ACM,就这样算了,也奋斗这么久了,人也不小了,就这样吧。现在看来,好像还是放不下,还是不甘心,两年啊!都习以为常了,这种生活方式,这种带着耳机刷代码的感觉,忘不了,放不下。也许我只是累了,等我休息下,又回来了。

感觉的事情,谁说的定呢?

要命的熟悉的感觉,要命的苦涩与喜悦。

记得那些差一题的遗憾,那些独挡两题的兴奋,全然过去了。

还是没能在最后完成自己的愿望。

ACM毁大学,AC毁一生!

说起来都是泪(累)。

不知道能不能就这样算了。不知道能不能就这样放下!


【代码一】

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<map>   using namespace std;   int n,m; long long ans;   struct node  //链表节点 {     int x;     struct node *first;  //前驱指针     struct node *next;  //后继指针 }*head,*are,*p,*q;   map<int,node*> addre;   void initial()  //创建一个长度为n+2,赋值为1-n的带头结点和尾节点的双向链表 {     head=(node *)malloc(sizeof(node));     are=head;     head->first=NULL;     head->next=NULL;     p=head;     for(int i=1;i<=n;i++)     {         q=(node *)malloc(sizeof(node));         p->next=q;         q->first=p;         q->next=NULL;         q->x=i;         addre[i]=q;         p=q;         are=q;     }     q=(node *)malloc(sizeof(node));     p->next=q;     q->first=p;     q->next=NULL;     are=q; }   void gotozero()//  清空链表,释放所有节点,以免超内存 {     p=are;     while(p!=head)     {         q=p;         p=p->first;         free(q);     }     free(p);     addre.clear(); }   node* find(int x)  //在链表中查找值为x的节点,返回该节点的指针 {     p=head->next;     while(p->x!=x)p=p->next;     return p; } void delet(node* u)  //删除指针u指向的节点 {     u->first->next=u->next;     u->next->first=u->first;     free(u); }   void insert(node* u,int x)//在指针u指向的节点前面插入一个值为x的节点 {     q=(node *)malloc(sizeof(node));     q->x=x;     addre[x]=q;     q->first=u->first;     q->next=u;     u->first->next=q;     u->first=q; }   void cul1() //逆向处理 {     int num=1;     p=are->first;     while(p!=head)     {         if(num%2==1)ans+=p->x;         p=p->first;         num++;     } }   void cul2()//正向处理 {     int num=1;     p=head->next;     while(p!=are)     {         if(num%2==1)ans+=p->x;         p=p->next;         num++;     } }   void output()  //将链表按中节点的值按顺序输出 {     p=head->next;     while(p->next!=NULL)printf("%d ",p->x),p=p->next;     printf("\n"); }   int main() {     int u,x,y;     int i,j;int r=1;     while(scanf("%d%d",&n,&m)!=EOF)     {         int flag=0;         ans=0;         initial();           while(m--)         {             scanf("%d",&u);             if(u==4)flag++;               else             {                 scanf("%d%d",&x,&y);                 if(u==1)                 {                     delet(addre[x]);                     if(flag%2==0)insert(addre[y],x);                     else insert(addre[y]->next,x);                 }                   else if(u==2)                 {                     delet(addre[x]);                     if(flag%2==0)insert(addre[y]->next,x);                     else insert(addre[y],x);                 }                   else                 {                     q=addre[x];                     p=addre[y];                     q->x=y;                     p->x=x;                     addre[x]=p;                     addre[y]=q;                 }               }             //output();         }           flag%2?cul1():cul2();           printf("Case %d: %lld\n",r++,ans);           gotozero();       }     return 0; }   /**************************************************************     Problem: 1329     User: 20114045007     Language: C++     Result: Accepted     Time:660 ms     Memory:5652 kb ****************************************************************/ 


【代码二】

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<map>   using namespace std;   int n,m; long long ans;   struct node  //链表节点 {     int x;     struct node *first;  //前驱指针     struct node *next;  //后继指针 }*head,*are,*p,*q;   map<int,node*> addre;   void initial()  //创建一个长度为n+2,赋值为1-n的带头结点和尾节点的双向链表 {     head=(node *)malloc(sizeof(node));     are=head;     head->first=NULL;     head->next=NULL;     p=head;     for(int i=1;i<=n;i++)     {         q=(node *)malloc(sizeof(node));         p->next=q;         q->first=p;         q->next=NULL;         q->x=i;         addre[i]=q;         p=q;         are=q;     }     q=(node *)malloc(sizeof(node));     p->next=q;     q->first=p;     q->next=NULL;     are=q; }   void gotozero()//  清空链表,释放所有节点,以免超内存 {     p=are;     while(p!=head)     {         q=p;         p=p->first;         free(q);     }     free(p);     addre.clear(); }   void delet()  //删除指针u指向的节点 {     q->first->next=q->next;     q->next->first=q->first; }   void insert(node* u,int x)//在指针u指向的节点前面插入一个值为x的节点 {     q->x=x;     addre[x]=q;     q->first=u->first;     q->next=u;     u->first->next=q;     u->first=q; }   void cul1() //逆向处理 {     int num=1;     p=are->first;     while(p!=head)     {         if(num%2==1)ans+=p->x;         p=p->first;         num++;     } }   void cul2()//正向处理 {     int num=1;     p=head->next;     while(p!=are)     {         if(num%2==1)ans+=p->x;         p=p->next;         num++;     } }   int main() {     int u,x,y;     int i,j;int r=1;     while(scanf("%d%d",&n,&m)!=EOF)     {         int flag=0;         ans=0;           if(r!=1)gotozero();           initial();           while(m--)         {             scanf("%d",&u);             if(u==4)flag++;               else             {                 scanf("%d%d",&x,&y);                 if(u==1)                 {                     q=addre[x];                     delet();                     if(flag%2==0)insert(addre[y],x);                     else insert(addre[y]->next,x);                 }                   else if(u==2)                 {                     q=addre[x];                     delet();                     if(flag%2==0)insert(addre[y]->next,x);                     else insert(addre[y],x);                 }                   else                 {                     q=addre[x];                     p=addre[y];                     q->x=y;                     p->x=x;                     addre[x]=p;                     addre[y]=q;                 }               }         }           flag%2?cul1():cul2();           printf("Case %d: %lld\n",r++,ans);       }     return 0; } /**************************************************************     Problem: 1329     User: 20114045007     Language: C++     Result: Accepted     Time:588 ms     Memory:5652 kb ****************************************************************/