「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
题目描述
Description
Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue…
The Lunar New Year was approaching, but unluckily the Little Cat still had schedules going here and there. Now, he had to travel by train to Mianyang, Sichuan Province for the winter camp selection of the national team of Olympiad in Informatics.
It was one o’clock a.m. and dark outside. Chill wind from the northwest did not scare off the people in the queue. The cold night gave the Little Cat a shiver. Why not find a problem to think about? That was none the less better than freezing to death!
People kept jumping the queue. Since it was too dark around, such moves would not be discovered even by the people adjacent to the queue-jumpers. “If every person in the queue is assigned an integral value and all the information about those who have jumped the queue and where they stand after queue-jumping is given, can I find out the final order of people in the queue?” Thought the Little Cat.
分析
分析:线段树好题 观察发现,最后一个人插入的位置是固定的联想到逆序读入,维护一颗线段树,区间存储剩余的位
核心查询代码:(原因理解下面Hint)
if(p<=sum[i<<1])update(p,v,lson);
else update(p-sum[i<<1],v,rson);
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 200000 + 10;
int sum[maxn<<2], ans[maxn<<2], pos[maxn], val[maxn];
int n;
void pushup(int root){
sum[root] = sum[root<<1] + sum[root<<1|1];
}
void build(int root, int l, int r){
sum[root] = r - l +1; //初始化
if (l == r) return;
int m = (l+r) >> 1;
build(root<<1, l, m);
build(root<<1|1, m+1, r);
}
void update(int root, int l, int r, int pos, int val){
if (l == r){
ans[root] = val;
sum[root] --;
return;
}
int m = (l+r) >> 1;
if (pos <= sum[root<<1]) update(root<<1, l, m, pos, val); //核心部分
else update(root<<1|1, m+1, r, pos-sum[root<<1], val);
pushup(root);
}
int g = 0;
void print(int root, int l, int r){ // 打印叶子结点 可以不处理行末空格
if (l == r){
printf("%d ", ans[root]);
return;
}
int m = (l+r) >> 1;
print(root<<1, l, m);
print(root<<1|1, m+1, r);
}
int main(){
while (scanf("%d", &n) != EOF){
for (int i = 0; i<n; i++)
scanf("%d%d", &pos[i], &val[i]);
build(1, 1, n);
for (int i = n-1; i>=0; i--){
update(1, 1, n, pos[i]+1, val[i]); // pos + 1
}
print(1, 1, n);
puts("");
}
return 0;
}
Hint
线段树节点中保存这一段中的空位数,然后倒序对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个空位才能插入)