/*题意:有n个人,给出n个人要插入的位置与其价值,输出最后的价值*/
/*【题解】:
线段树节点中保存这一段中的空位数,然后倒序对pos插入:
例如: 0 77
1 51
1 33
2 69
先取: 2 69 —— —— —69— —— (需要前面有3个空位才能插入)
然后取: 1 33 —— —33— —69— —— (需要前面有2个空位才能插入)
然后取: 1 51 —— —33— —69— —51— (需要前面有2个空位才能插入) 前面只有1个空位 故插入后面空格
然后取: 0 77 —77— —33— —69— —51— (需要前面有1个空位才能插入)
*/
/*由于左后一个人插进来后他的位置肯定是固定的
我们就可以倒着来插,最后一个固定后,如果倒数第二个插入的序号小于当前那么就往前插到序号上,否则往后插,往后的话序号需要减去当前这个数左边的空位数
因为左右都是从0位置开始标记的
因此结构体里需要维持节点左右边的空位个数,当前插队序号小于左边空位插左边,大于的话插右边,但是需要需要减去左边空位。。因为右边也是从0位置开始算起的,并且
我们是倒着插,所以空位个数才是当时的需要插的位置,已经被占的位置当时还不存在..*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
int l, r, sum;
int mark;
}dp[1000005];
int p[200005];
int v[200005];
int ans[200005];
void Create(int l, int r, int i)
{
dp[i].l = l;
dp[i].r = r;
dp[i].sum = (r - l + 1);
if (l == r)
{
return;
}
int mid = (l + r) >> 1;
Create(l, mid, i * 2);
Create(mid + 1, r, i * 2 + 1);
}
void Change(int a, int b, int i)//a表示空格数量,b为输入的值,i为节点
{
if (dp[i].l == dp[i].r)
{
dp[i].sum = 0;
ans[dp[i].l] = b;
return;
}
int mid = (dp[i].l + dp[i].r) / 2;
//优先放在左边
if (a <= dp[i * 2].sum)//如果左边放的下
{
Change(a, b, i * 2);
}
else//左边放不下
Change(a - dp[i * 2].sum, b, i * 2 + 1);
dp[i].sum = dp[i * 2].sum + dp[i * 2 + 1].sum;
}
int main()
{
int n;
while (cin>>n)
{
Create(1, n, 1);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &p[i], &v[i]);
}
for (int i = n - 1; i >= 0; i--)
{
Change(p[i] + 1, v[i], 1);
}
for (int i = 1; i <= n; i++)
{
if (i != 1)
{
cout << " ";
}
cout << ans[i];
}
cout << endl;
}
return 0;
}
Buy Tickets
最新推荐文章于 2022-02-21 22:57:00 发布