线段树 --- (区间维护+逆推)

Buy
Tickets
Time Limit:4000MS    
Memory Limit:65536KB     64bit IO
Format:
%I64d & %I64u

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.

Input

There will be several test cases in the input. Each test case consists of
N + 1 lines where N (1 ≤ N ≤ 200,000) is given in the
first line of the test case. The next N lines contain the pairs of
values Posi and Vali in the increasing
order of i (1 ≤ iN). For each i, the
ranges and meanings of Posi and Vali are
as follows:

  • Posi ∈ [0, i ? 1] — The i-th person
    came to the queue and stood right behind the Posi-th
    person in the queue. The booking office was considered the 0th person and the
    person at the front of the queue was considered the first person in the
    queue.

  • Vali ∈ [0, 32767] — The i-th person was
    assigned the value Vali.

There no blank lines between test cases. Proceed to the end of input.

Output

For each test cases, output a single line of space-separated integers which
are the values of people in the order they stand in the queue.

Sample Input

4
0 77
1 51
1 33
2 69
4
0 20523
1 19243
1 3890
0 31492

Sample Output

77 33 69 51
31492 20523 3890 19243

Hint

The figure below shows how the Little Cat found out the final order of people
in the queue described in the first test case of the sample input.

【题目大意】;有n个人买火车票,期初没有人排队,然后陆续的来人,来一个人就给他分配一个数字,而且会有人插队,要你输出最后的队伍顺序。
【题目分析】:这是一个经典的逆推问题。需要注意到,最后一个插入的值位置的固定的,也就是最后一个插入的值可以在它想要插入的位置,所以,先保存所以整数对,之后在倒序插入序列中。那到底应该用什么数据结构实现呢?这里我们发现,可以用线段树来解决这一问题,每一个区间添加一个域
num,表示该区间还能放置的位置数,或者说,表示该区间还能放置的最大的序号值(当然,这是相对于最左边的区间而已的,所以,右区间的话,中间还有一步维护操作。
source code:


#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#define MAX 200010
using namespace std;
struct Node
{
int p,v;
} node[MAX];
struct TNode
{
int l,r;
int c;
} tree[4*MAX];
int N;
int ans[MAX];
void build(int l,int r,int x)
{
tree[x].c=r-l+1; //该区间的大小,开始写反了,wa了两次
tree[x].l=l;
tree[x].r=r;
if(l==r) //到底了,返回
return;
int mid=(l+r)>>1;
build(l,mid,2*x);
build(mid+1,r,2*x+1);
}

void Insert(int x,int pos,int val) //下标 位置(position) 价值(value)
{
tree[x].c--; //该区间的空格数减少1
if(tree[x].l==tree[x].r) //直到找到了一个合适的空格来存放该位置
{
ans[tree[x].l]=val; //将价值映射到ans中
return;
}
if(tree[2*x].c>=pos) //该区间的剩余空格数大于位置的坐标,往前探寻
Insert(2*x,pos,val);
else //该区间剩余空格数小于位置的坐标,往后找空格
Insert(2*x+1,pos-tree[2*x].c,val);
}

int main()
{
while(~scanf("%d",&N))
{
build(1,N,1);
int i;
for(i=1;i<=N;i++)
{
scanf("%d%d",&node[i].p,&node[i].v);
node[i].p++; //输入是从0开始的,加1变为从1开始
}
for(i=N;i>=1;i--) //重点:逆序更新
{
Insert(1,node[i].p,node[i].v);
}
for(i=1;i<N;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[N]);
}
return 0;
}

线段树 --- (区间维护+逆推),布布扣,bubuko.com

时间: 2024-10-15 08:05:32

线段树 --- (区间维护+逆推)的相关文章

hdu 1556 Color the ball(线段树区间维护+单点求值)

传送门:Color the ball Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 25511    Accepted Submission(s): 12393 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele

POJ3468(线段树区间维护)

#include<cstdio> #define lson n<<1,l,mid #define rson (n<<1)|1,mid+1,r #define gmid (a[n].l+a[n].r)>>1 using namespace std; const int MAX_N=100005; typedef long long LL; struct node{ int l,r; LL sum,lazy; }a[MAX_N<<2]; void P

Codevs-4919 线段树练习4(区间加上一个值并求摸个区间整除k的数的个数,线段树+数组维护)

给你N个数,有两种操作 1:给区间[a,b]内的所有数都增加X 2:询问区间[a,b]能被7整除的个数 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数.如果第一个数是add,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是count,表示统计区间[a,b]能被7整除的个数 输出描述 Output Description 对于每个询问输出一行一个答案 样例输入 Sample

P2023 [AHOI2009]维护序列 (线段树区间修改查询)

题目链接:https://www.luogu.org/problemnew/show/P2023 一道裸的线段树区间修改题,懒惰数组注意要先乘后加 #include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxx = 400010; LL tree[maxx],lazy1[maxx],lazy2[maxx],a[maxx],mod; int n; void build(int l,int r,in

HDU 5861 Road(线段树 区间修改 单点查询)

Road Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1132    Accepted Submission(s): 309 Problem Description There are n villages along a high way, and divided the high way into n-1 segments. E

POJ 3667 线段树区间合并

http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html 用线段树,首先要定义好线段树的节点信息,一般看到一个问题,很难很快能确定线段树要记录的信息做线段树不能为了做题而做,首先线段树是一种辅助结构,它是为问题而生的,因而必须具体问题具体分析回忆一下RMQ问题,其实解决RMQ有很多方法,根本不需要用到线段树,用线段树解决RMQ,其实是利用线段树的性质来辅助解决这个问题回忆一下求矩形面积并或周长并的问题,一般使用的是扫描

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

codeforces 482B. Interesting Array【线段树区间更新】

题目:codeforces 482B. Interesting Array 题意:给你一个值n和m中操作,每种操作就是三个数 l ,r,val.就是区间l---r上的与的值为val,最后问你原来的数组是多少?如果不存在输出no 分析:分析发现要满足所有的区间,而一个点上假如有多个区间的话,这个点的值就是所有区间或的值,因为只有这样才能满足所有区间的,把所有位上的1都保存下来了,那么可以发现用线段树来维护,但是那么怎么判断满不满足条件呢?可以也用线段树,更新了之后在整个维护一遍看看满不满足题意,如

【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)

[BZOJ3638]Cf172 k-Maximum Subsequence Sum Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少.1 ≤ n ≤ 105,1 ≤ m ≤ 105,1 ≤ l ≤ r ≤ n, 1 ≤ k ≤ 20 Sample Input 9 9 -8 9 -1 -1 -1 9 -8 9 3 1 1 9 1 1 1 9 2 1 4 6 3 Sample Output 17 25