寒假集训专题五-But Tickets
Buy tickets--插队问题
题意
给n个数对pos,val,表示某人要插队的位置和权值,按顺序输出队伍的权值
思路
若按找正序想,难以确定每个人的位置
若按照倒序想,首先可以确定最后一个人的位置,然后再从后往前依次确定每个人的位置(若该位置有空,则插入,若没有,则往后查找)
因为涉及到查找,当目标是第一个空却需要插入至最后一个空此时的时间是2e5,有2e5个数一定超时,所以采用线段树的方法。
先把位置变成1,n
eg.
拿第一个举例
插入3 49
找到3的位置,直接插入
插入 2 33
找到 2 的位置,大小足够 插入
插入2 51
到 1-2的结点 大小为1(已经被占了一个)
所以转移到插入3-4结点
此时的插入要求的位置也要变化 p=p-tr[ u<<1 ]
有1个位置,3已经被用过,只能插入4
记得用scanf 和 printf
AC代码
#include
#include
#include
#include
using namespace std;
typedef pair PII;
const int N=2e5+7;
int b[N];
struct node{
int l,r,size;
}tr[N<<2];
void bt(int u,int l,int r)
{
if(l==r)
{
tr[u]={l,r,1};
return;
}
tr[u]={l,r,0};
int mid=l+r>>1;
bt(u<<1,l,mid);
bt(u<<1|1,mid+1,r);
tr[u].size=tr[u<<1].size+tr[u<<1|1].size;
}
void update(int u,PII &p)
{
if(tr[u].l==tr[u].r)
{
b[tr[u].l]=p.second;
tr[u].size--;
return ;
}
if(tr[u<<1].size>=p.first)
{
update(u<<1,p);
}
else
{
p.first=p.first-tr[u<<1].size;
update(u<<1|1,p);
}
tr[u].size=tr[u<<1].size+tr[u<<1|1].size;
}
signed main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(b,0,sizeof(b));
vector ve(n);
for(int i=0;i=0;i--)
{
update(1,ve[i]);
}
for(int i=1;i<=n;i++)
{
printf("%d ",b[i]);
}
printf("\n");
}
}