hdu 7072 Boring data structure problem
题意:
- 双向队列,逐个在队首或队尾添加元素,在这过程中也会删除队中的一些元素,每次 ′ Q ′ 'Q' ′Q′ , 询问队列最中间 ( m i d ) (mid) (mid) 的元素是哪个
分析:
-
双向队列的妙题(绝妙!)
-
用双向队列 q l ql ql 和 q r qr qr 分别来存左侧和右侧添的元素,每进行一次操作,都要重新维护两个队列,保证 q r qr qr的 队首为 m i d mid mid
-
这题我觉得最妙的就是,这样处理下来,将要删除的元素在维护更新的过程中就将其排除出去了
(类似数组的滚动操作)
反思:
-
我的思路就是直接去查询位置 m i d mid mid 的元素,但被删除操作卡了
我对删除操作的处理,将删除的元素的下标做一下记忆化,每次查询 m i d mid mid ,所要查询的值为 ( m i d + x ) (mid+x) (mid+x) ( x x x 表示在下标 m i d + x mid+x mid+x 之前有 x x x 个被删除了,因此第 m i d + x mid+x mid+x 即为最中间的坐标)
-
思路的转换
- 要求第 m i d mid mid 个,若保证我一直知道 m i d mid mid ,便可直接输出,只要维护两个队列中元素个数相等即可
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+5;;
int vis[N];
deque <int> ql, qr;
int l,r;
void up()
{
while(l > r)
{
while(!vis[ql.back()]) ql.pop_back();
qr.push_front(ql.back()); ql.pop_back();
r++; l--;
vis[qr.front()] = 2;
}
while(r > l+1)
{
while(!vis[qr.front()]) qr.pop_front();
ql.push_back(qr.front()); qr.pop_front();
r--; l++;
vis[ql.back()] = 1;
}
}
signed main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int q;
cin>>q;
int tot=0;
while(q--)
{
char op;
cin>>op;
if(op=='L')
{
l++; vis[++tot] = 1;
ql.push_front(tot);
up();
}
else if(op=='R')
{
r++; vis[++tot] = 2;
qr.push_back(tot);
up();
}
else if(op=='G')
{
int x;
cin>>x;
if(vis[x]==1) l--;
else r--;
vis[x] = 0;
up();
}
else
{
while(!vis[qr.front()]) qr.pop_front();
cout<<qr.front()<<endl;
}
}
return 0;
}