这道题数组模拟双向链表,其实就是将单向链表改成双向的,左右两个数组标记一下即可,循环链表将头尾连接即可。
题意:给出一个数n,表示存在一个整数序列1……n,然后进行四种操作:
操作一:输入x,y,表示将x移到y的左边(若x本来就在y的左边则忽略);
操作二:输入x,y,表示将x移到y的右边(若x本来就在y的右边则忽略);
操作三:输入x,y,表示交换x和y。
操作四:将整个序列倒置。
最后求操作后的整个序列奇数项的和。
思路:这个题很巧妙,在整个过程中,逆序操作最耗时间,由于题目只需要求奇数项的和,在进行逆序操作时,不用真的进行操作,只需要记录逆序的次数即可,若是奇数次,则最后求整个序列的偶数项之和,偶数次就是求奇数项之和。还有一点,操作四的进行与否会对前两种操作有一点影响,需要稍作处理。
借鉴博客https://blog.csdn.net/acm_fighting/article/details/50983756
AC代码:
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
using namespace std;
typedef long long LL;
const int maxn= 100010;
int left[maxn],right[maxn];
void link(int L, int R) { //连接L和R,L在左边
right[L] = R;
left[R] = L;
}
int main() {
int n,m;
while(~scanf("%d%d",&n,&m)) {
for(int i=0; i<=n; i++) {
link(i,i+1);
}
//循环链表
// left[0]=n;
// right[n]=0;
int op,flag=0,x,y;
while(m--) {
scanf("%d",&op);
if(op==4) { //判断是否进行逆序操作
flag=!flag;
continue;
}
scanf("%d%d",&x,&y);
if(op==3 && right[y]==x) swap(x,y); //方便后面判断交换是否相邻
if(op!=3 && flag) op=3-op; //进行逆序操作后,原来的左边变成右边,右边变成左边
if(op==1 && left[y]==x) continue;
if(op==2 && right[y]==x) continue;
int lx=left[x],rx=right[x],ly=left[y],ry=right[y];
if(op==1) { //将x移到y的左边
link(lx,rx); //x左右相连
link(ly,x); //y左和x
link(x,y); //x和y
} else if(op==2) { //将x移到y的右边
link(lx,rx); //x左右相连
link(y,x); //y和x
link(x,ry); //x和y右
} else if(op==3) { //交换x和y
if(right[x]==y) { //当x和y相邻时
link(lx,y);
link(y,x);
link(x,ry);
} else { //当x和y不相邻时
link(lx,y);
link(y,rx);
link(ly,x);
link(x,ry);
}
}
}
LL sum=0;
int b=0;
for(int i=1; i<=n; i++) {
b=right[b];
if(i%2)
sum+=b;
}
if(flag && n%2==0)
sum=(LL)n*(n+1)/2-sum;
//如果逆序操作次数为奇数,则最终结果求的是整个序列的偶数项之和,此处是用 序列总和减去奇数项之和
printf("%lld\n",sum);
}
return 0;
}
我用vector做的,但是C++11报运行时错误,C++11报运行时错误,1e5也没道理越界诶 奇奇怪怪... 有聚聚们知道错误地方的话请告知嗷
我的代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int m,n;
while(scanf("%d%d",&n,&m)!=EOF){
vector<int> vt;
long long ans = 0;
for(int i=1;i<=n;i++)
vt.push_back(i);
while(m--) {
int op,a,b;
cin>>op;
if(op==1||op==2||op==3)
cin>>a>>b;
if(op==1) {
// x 在 y 左边
vector<int>::iterator iter1=find(vt.begin(),vt.end(),a);
vector<int>::iterator iter2=find(vt.begin(),vt.end(),b);
for(int i=0;i<=(iter2-iter1-2);i++) {
*(iter1+i)=*(iter1+i+1);
}
*(iter2-1)=a;
}
if(op==2) {
// x 在 y 右边
vector<int>::iterator iter1=find(vt.begin(),vt.end(),a);
vector<int>::iterator iter2=find(vt.begin(),vt.end(),b);
for(int i=0;i<=(iter2-iter1-1);i++) {
*(iter1+i)=*(iter1+i+1);
}
*iter2=a;
}
if(op==3) {
//交换 x y
vector<int>::iterator iter1=find(vt.begin(),vt.end(),a);
vector<int>::iterator iter2=find(vt.begin(),vt.end(),b);
*iter1=b;
*iter2=a;
}
if(op==4) {
reverse(vt.begin(),vt.end());
}
}
// for(int i=0;i<n;i++)
// cout << vt[i] << " ";
for(int i=0;i<n;i+=2)
ans += vt[i];
cout << ans << endl;
vt.clear();
}
return 0;
}