您的位置:首页 > 其它

双链表--uva12657 Boxes in a Line 从入门到放弃

2017-11-29 22:31 495 查看
分析:

/*
思路:用双向队列记录点的左右节点,每次移动进行更新。
op == 4的时候需要链表反转,这个操作很麻烦,不如直接用inv记录。每次取反。inv为1的时候相当于不动,inv为0的时候我们的链表相当于反转的逆序。
拿1234来说,inv为1是4321.此时1 2 4 是2341,我们直接操作就是3-op2就是,2 2 4生成1342,生成2431的逆序。
而当n为奇数时,正逆求和一样;n为偶数时,我们求的反倒是下标是偶数的和,拿总和n*(n+1)/2减去就行了。
需要注意的是,考虑到bin(x,y)是x在左,y在右,所以调用前需要排好左右关系。
*/


ps:ans = ll(n)*(n+1)/2-ans这一句一定要把ll强制类型转换作用到n或n+1上,如果写成ans = ll(n*(n+1))/2-ans,n*(n+1)结果保存为int,数据已经丢失,再强制转化为long long,还是会错的。

代码:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <bitset>
#include <list>
#include <sstream>
#include <set>
#include <functional>
using namespace std;

const int maxn = 1e5+5;
typedef long long ll;
int l[maxn],r[maxn];

void bin(int x,int y)
{
r[x] = y;l[y] = x;
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int n,m,kcase =  0;
while(scanf("%d%d",&n,&m)!=EOF) {
for (int i = 1; i <= n; ++i)	//初始化
l[i] = i-1,r[i] = (i+1)%(n+1);
l[0] = n,r[0] = 1;

int op,x,y,flag = 0;
while(m--) {
scanf("%d",&op);
if(op == 4) flag = !flag;//判断
else{
scanf("%d%d",&x,&y);
if (op == 3 && r[y] == x) swap(y,x);//调成有序,大坑
else if(op != 3 && flag) op = 3-op;
if(op == 1 && l[y] == x) continue;
if(op == 2 && r[y] == x) continue;

int lx = l[x],ly = l[y],rx = r[x],ry = r[y];
if(op == 1) {bin(lx,rx);bin(ly,x);bin(x,y);}
else if(op == 2) {bin(lx,rx);bin(y,x);bin(x,ry);}
else if(op == 3 && rx == y) {bin(lx,y);bin(y,x);bin(x,ry);}
else {bin(lx,y);bin(y,rx);bin(ly,x);bin(x,ry);}
}
}

ll ans = 0;
int b = 0;
for (int i = 1; i <= n; ++i)
{
b = r[b];
if(i%2) ans += b;
}
if(flag && n%2 == 0) ans = ll(n)*(n+1)/2-ans;
printf("Case %d: %lld\n", ++kcase,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uva12657 双链表