//提前声明 此为写者的思路 可能读者读来有那么不解 慢慢体会吧 一起加油
uva11988 破碎的键盘
直接分析,给出一个字符串,我们先想到遇见【移动字符串,如果这个字符串很长,那么它的移动速度将会很慢,想想肯定就超时,那么如何节省时间的移动,我们就用链表来模拟移动,用数组的方式模拟链表移动。对于链表,我们首先要清楚就基本链表而言清楚链表,这样才能套用到数组的模拟之上。(清楚链表的基本结构,插入一个结点的方式等。。。)因此,我们结合题意不难想到cur光标位置出现的合理性,即用来标记前次的位置,即这次应当链接在哪段之后,则不遇见【和】的情况下的数组链表不难模拟出来。那么我们遇见【该如何呢,更印证cur光标的必然性,即改cur=0;别忘了还要将这链尾实现链接//此乃链表常识,再不断结合题意,last标记便易想出,此题即可解。
除此解法外,stl的list是真的强,与模拟数组相比,简直就是通俗易懂的典范代表。不能再典范了。
#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>
using namespace std;
int main()
{
char s[100005];
while(scanf("%s",s+1)!=EOF)
{
int next[100005]={0};
int last=0;
next[0]=0;
int l=strlen(s+1);
int cur=0;
for(int i=1;i<=l;i++)
{
char ch=s[i];
if(ch=='['){
cur=0;
}
else if(ch==']'){
cur=last;
}
else {
next[i]=next[cur];
next[cur]=i;
if(cur==last)
last=i;
cur=i;
}
}
for(int i=next[0];i!=0;i=next[i])
printf("%c",s[i]);
printf("\n");
}
return 0;
}
uva 12657 移动盒子
真心而言,明白上一题,这一题双向链表还是比较好想的,至于那刘汝佳的算法,真的是值得学习掌握的一种方法,它不仅仅只是这一道题的解法,更是一种解题的思路,化繁为简的思虑。值得细品。
#include <iostream>
#include <cstdio>
using namespace std;
int lef[100005];
int righ[100005];
void link(int x,int y){
righ[x]=y;
lef[y]=x;
}
int main()
{
int kase=0;
long long n,m;
while(cin>>n>>m){
for(int i=1;i<=n;i++){
lef[i]=i-1;
righ[i]=i+1;
}
righ[n]=0;
righ[0]=1;
lef[0]=0;
int inv=0;
int op,x,y;
for(int i=0;i<m;i++){
scanf("%d",&op);
if(op==4) {
inv=!inv;
continue;
}
scanf("%d%d",&x,&y);
if(inv&&op!=3) op=3-op;
if(op==1&&righ[x]==y) continue;
else if(op==2&&lef[x]==y) continue;
int lx=lef[x],rx=righ[x],ly=lef[y],ry=righ[y];
if(op==1){
link(lx,rx);link(ly,x);link(x,y);
}
else if(op==2){
link(lx,rx);link(y,x);link(x,ry);
}
else if(op==3){
if(righ[x]==y){
link(lx,y);link(y,x);link(x,ry);
}
else if(righ[y]==x){
link(ly,x);link(x,y);link(y,rx);
}
else{
link(lx,y);link(y,rx);link(ly,x);link(x,ry);
}
}
}
printf("Case %d: ",++kase);
long long int sum=0;
int d=0;
for(int i=1;i<=n;i++){
d=righ[d];
if(i%2!=0){
sum+=d;
}
}
if(inv&&n%2==0){
long long int sum2;
sum2=(n+1)*n/2;
sum=sum2-sum;
}
printf("%lld\n",sum);
}
}