您的位置:首页 > 其它

HDU 3436 题解

2016-07-06 10:16 393 查看
题目大意

有一个队列,开始时第i个数是i。

有三种操作。

Top x:把x放到队头。

Query x:查询x是第几个数。

Rank x:查询第x个数。

n<=10^8,m<=10^5,x<=n

我的做法

离散化+线段树

把top和query中的x离散化,把用不到的区间缩成一个点。

记下每个数在线段树中的位置,线段树中每个位置中的第一个数。

top:把原来的数删除,添加一个新数。

query:输出x在线段树中的位置到线段树最后一个位置之间数的个数。

rank:查询第x个数。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
struct tree
{
int l,r;
int v;
int sum;
tree *ls,*rs;
tree()
{
l=r=sum=0;
ls=rs=0;
v=0;
}
};
tree *top;
map<int,int> a,b;
int left[500010];
int right[500010];
int cnt2=0;
void mt(tree *&p)
{
if(p->l==p->r)
return;
p->sum=p->ls->sum+p->rs->sum;
}
void build(tree *&p,int l,int r)
{
if(!p)
p=new tree;
p->l=l;
p->r=r;
p->v=0;
p->sum=0;
if(p->l==p->r)
return;
int mid=(l+r)>>1;
build(p->ls,l,mid);
build(p->rs,mid+1,r);
}
void insert(tree *&p,int x,int v,int t)
{
if(p->l==p->r)
{
p->sum+=t;
if(t==1)
{
a[v]=p->l;
b[p->l]=v;
}
return;
}
int mid=(p->l+p->r)>>1;
if(x<=mid)
insert(p->ls,x,v,t);
else
insert(p->rs,x,v,t);
mt(p);
}
void insert2(tree *&p,int x,int l,int r)
{
if(p->l==p->r)
{
p->sum+=r-l+1;
p->v=++cnt2;
left[cnt2]=l;
right[cnt2]=r;
return;
}
int mid=(p->l+p->r)>>1;
if(x<=mid)
insert2(p->ls,x,l,r);
else
insert2(p->rs,x,l,r);
mt(p);
}
int query(tree *&p,int l,int r)
{
if(l<=p->l&&r>=p->r)
return p->sum;
int s=0;
int mid=(p->l+p->r)>>1;
if(l<=mid)
s+=query(p->ls,l,r);
if(r>mid)
s+=query(p->rs,l,r);
return s;
}
int rr(tree *&p,int k)
{
if(p->l==p->r)
{
if(!p->v)
return b[p->l];
return left[p->v]+k-1;
}
int s=p->rs->sum;
if(k<=s)
return rr(p->rs,k);
return rr(p->ls,k-s);
}
int d[100010];
int xx[100010];
int e[100010];
int main()
{
int t;
scanf("%d",&t);
top=0;
int tt=0;
while(t--)
{
memset(d,0,sizeof(d));
memset(xx,0,sizeof(xx));
memset(e,0,sizeof(e));
a.clear();
b.clear();
printf("Case %d:\n",++tt);
int n,m;
scanf("%d%d",&n,&m);
build(top,1,3*m);
int i;
int x;
int cnt=0;
int tot=0;
for(i=1;i<=m;i++)
{
char s[10];
scanf("%s%d",s,&xx[i]);
if(s[0]=='T')
d[i]=1;
else if(s[0]=='R')
d[i]=2;
else
d[i]=3;
if(d[i]!=2)
e[++tot]=xx[i];
}
e[++tot]=1;
e[++tot]=n;
sort(e+1,e+tot+1);
tot=unique(e+1,e+tot+1)-e-1;
for(i=tot;i>=1;i--)
{
insert(top,++cnt,e[i],1);
if(i!=1&&e[i]!=e[i-1]+1)
insert2(top,++cnt,e[i-1]+1,e[i]-1);
}
for(i=1;i<=m;i++)
{
x=xx[i];
if(d[i]==1)
{
int v=a[x];
insert(top,v,x,-1);
insert(top,++cnt,x,1);
}
else if(d[i]==2)
printf("%d\n",rr(top,x));
else
printf("%d\n",query(top,a[x],cnt));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: