这种签到题场上居然不过,果然是自己的链表水平太差.
题意
维护一个数据结构.要求能进行四种操作:
- L L L 在左边插入一个数字
- R R R 在右边插入一个数字
- G G G 删除一个已经有的数
- Q Q Q 询问在中间的数字,有偶数个的话回答偏右的那个.
保证每次插入的数字是
1
,
2
,
3...
1,2,3...
1,2,3...按顺序的自然数,不会重复.
操作的次数为
1
0
7
10^7
107,后面两个操作的次数不超过
1.5
×
1
0
6
1.5\times 10^6
1.5×106,只有一组数据.
题解
显然不能用带
l
o
g
log
log的数据结构维护.
考虑使用两个
d
e
q
u
e
deque
deque进行维护,保持右边的
s
i
z
e
size
size和左边相等或者比左边多一个,则右边
d
e
q
u
e
deque
deque的最左边那个即为答案.
删除的时候就直接标记,只用两个数表示两边数字的个数可以忽略掉已经删除的数.
我没有用这种维护方法,而是使用了一种自创新数据结构:可查链表.
众所周知链表是可以
O
(
1
)
O(1)
O(1)插入删除但是需要
O
(
n
)
O(n)
O(n)进行查找的一种数据结构.
但是本题中,按顺序插入没有重复的特点保证了我们可以在插入的时候直接标记
x
x
x的位置
i
d
x
id_x
idx,这样删除的时候直接删除
i
d
x
id_x
idx,并且动态维护中间数
a
n
s
ans
ans,由于插入和删除操作每次只有一个数,因此中间数每次也最多移动一位,只要用一个
l
e
n
len
len标记当前数据结构中数字的个数即可对这个答案进行维护了,所有的操作复杂度均为
O
(
1
)
O(1)
O(1).
不幸的是,由于我对链表不甚熟练,场上并没有调出来.(比赛结束后删掉四个字符就AC了,当场去世.)
昨天牛客的时候也是拖的假匈牙利板子,不知道自己上辈子造了什么孽.
贴一下自己的渣代码.由于开
2
×
1
0
7
2\times 10^7
2×107长度的数组会导致
M
L
E
MLE
MLE,只能开
1600
万
1600万
1600万,不是非常严谨,但由于本题只有一组数据,可以通过.
const int yuzu=8e6;
typedef int fuko[yuzu<<1|13];
fuko net,pre,id,a;
int main() {
int q,i,cntl=yuzu,len=0,cntr=yuzu+1,now=0,ans=-1;
/*
本题所使用的可查链表有左头和右头,分别向两边添加的时候只要普通的添加即可.
初始位置在maxn>>1的位置.
*/
for (scanf("%d",&q);q--;) {
char op; int x;
auto addl=[&](int x) {
++len,id[x]=cntl;
net[cntl]=~a[cntl+1]?cntl+1:net[cntl];
pre[cntl]=cntl-1;
a[cntl]=x;
if (!~ans) { // 考虑到加入的数有可能被全部删去,在没有数的时候就将ans置-1.
ans=cntl--;
return;
}
--cntl;
if (len&1) ans=pre[ans]; // 向左边添加数字到奇数个的时候ans要左移.
};
auto addr=[&](int x) {
++len,id[x]=cntr;
net[cntr]=cntr+1;
pre[cntr]=~a[cntr-1]?cntr-1:pre[cntr];
a[cntr]=x;
if (!~ans) {
ans=cntr++;
return;
}
++cntr;
if (!(len&1)) ans=net[ans]; // 这边也是因此类推.
};
auto del=[&](int x) {
pre[net[x]]=pre[x];
net[pre[x]]=net[x];
a[x]=-1; // 删掉的数标记为-1.
--len;
if (!len) { // 删光了所有数,ans要等于-1,随时待命,加入第一个数的时候就把ans放到这个数的位置.
ans=-1;
return;
}
if (x==ans) {
ans=len&1?pre[ans]:net[ans];
} else if (x<ans) {
!(len&1)?ans=net[ans]:0;
} else {
len&1?ans=pre[ans]:0;
} // ans移动分为刚好删掉了中间数,删掉的数在左边或者右边来讨论.
};
scanf("\n%c",&op);
if (op=='L') {
addl(++now);
} else if (op=='R') {
addr(++now);
} else if (op=='G') {
scanf("%d",&x);
del(id[x]);
} else {
printf("%d\n",a[ans]);
}
}
}