Description
输入n个有序对< pi, vi >,pi表示在第pi个位置后面插入一个值为vi的人,并且pi是不降的。输出最终得到的v的序列
Input
多组用例,每组用例第一行为有序对组数n,之后n行每行两个整数表示一个有序对,以n=0结束输入
Output
对于每组用例,输出最后得到的序列
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

单点插入线段树——所以建树的时候叶子节点应该为大于n的第一个数(cnt = 2 ^ k  > n)

建树的时候我们logn找到该点向下更新叶子和向上更新根节点特别的我们要记录这个节点还有多少空位

为什么要逆序?

因为最后的元素可以确定位置,而忽略前面元素的影响

例如 0 10 0 11

我们逆序来插入值     11   ?

?代表还有空

11插入后,那个节点记录表示空位是0

所以插入0 10的时候会通过判断来往?的位置走~

差不多,自己手想一下就好

void build()
{
int s;
for(s = 1;s < n;s <<= 1);
//之所以要出来大于n画一画就好了,n那一层就算没有占满,也要开一层下面的吧 for(int i = s;i < 2 * s;i++)//叶子
{
tree[i].l = tree[i].r = i - s + 1;
tree[i].cnt = 1;
} for(int i = s-1;i >= 1;i--)//根
{
tree[i].l = tree[2*i].l;
tree[i].r = tree[2*i+1].r;
tree[i].cnt = tree[2*i].cnt + tree[2*i+1].cnt;
}
}

这是第一种建树,也可以常规来

void build(int rt, int left, int right)
{
tree[rt].l = left;
tree[rt].r = right;
tree[rt].cnt = right - left + 1;
if(left == right)
return;
int mid = (left + right) >> 1;
build(rt<<1,left,mid);
build(rt<<1|1,mid + 1,right);
}

code......

//****单点更新线段树
#include <cstdio>
#include <algorithm>
#include <string.h>
#define inf (1 << 29)
using namespace std;
const int maxn = 2e5 + 100;
struct node
{
int pos;
int num;
}p[maxn];
struct node2{
int l,r,cnt;
}tree[maxn << 2];
int n,ans[maxn];
void build(int rt, int left, int right)
{
tree[rt].l = left;
tree[rt].r = right;
tree[rt].cnt = right - left + 1;
if(left == right)
return;
int mid = (left + right) >> 1;
build(rt<<1,left,mid);
build(rt<<1|1,mid + 1,right);
}
/*void build()
{
int s;
for(s = 1;s < n;s <<= 1);
//之所以要出来大于n画一画就好了,n那一层就算没有占满,也要开一层下面的吧 for(int i = s;i < 2 * s;i++)//叶子
{
tree[i].l = tree[i].r = i - s + 1;
tree[i].cnt = 1;
} for(int i = s-1;i >= 1;i--)//根
{
tree[i].l = tree[2*i].l;
tree[i].r = tree[2*i+1].r;
tree[i].cnt = tree[2*i].cnt + tree[2*i+1].cnt;
}
}*/
void insertpoint(int i,int pos,int num)
{
if(tree[i].l == tree[i].r)
{
ans[tree[i].l] = num;
tree[i].cnt = 0;
return;
} if(pos <= tree[2*i].cnt)
insertpoint(2*i,pos,num);
else
insertpoint(2*i+1,pos - tree[2*i].cnt,num);
tree[i].cnt--;
}
int main()
{
while(~scanf("%d",&n))
{
int k = 0;
for(k = 1;k < n;k <<= 1);
build(1,1,k);
for(int i = 0;i < n;++i)
scanf("%d%d",&p[i].pos,&p[i].num);
for(int i = n - 1;i >= 0;i--)
insertpoint(1,p[i].pos + 1,p[i].num);
for(int i = 1;i <= n;i++)
{
printf("%d%c",ans[i],i == n ? '\n' : ' ');
}
} return 0; }

POJ2828线段树单点更新——逆序更新的更多相关文章

  1. poj2828 线段树单点更新

    Buy Tickets Time Limit: 4000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java ...

  2. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  3. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

  4. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  5. POJ 1804 Brainman(5种解法,好题,【暴力】,【归并排序】,【线段树单点更新】,【树状数组】,【平衡树】)

    Brainman Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 10575   Accepted: 5489 Descrip ...

  6. HDU 1754 I Hate It 线段树单点更新求最大值

    题目链接 线段树入门题,线段树单点更新求最大值问题. #include <iostream> #include <cstdio> #include <cmath> ...

  7. HDU 1166 敌兵布阵(线段树单点更新)

    敌兵布阵 单点更新和区间更新还是有一些区别的,应该注意! [题目链接]敌兵布阵 [题目类型]线段树单点更新 &题意: 第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N< ...

  8. poj 2892---Tunnel Warfare(线段树单点更新、区间合并)

    题目链接 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensiv ...

  9. HDU 1166 敌兵布阵(线段树单点更新,板子题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

随机推荐

  1. this高级应用 - 域隔离

    在js环境中,this有很多指向(window.dom.object等),巧妙的利用this,可以有效的防止变量或方法被外界污染,保证代码健壮性,实例如下. demo: <!DOCTYPE ht ...

  2. rpm安装jdk7

    原文:http://www.centoscn.com/image-text/config/2015/0208/4658.html 系统环境:centos-6.5 安装方式:rpm安装 软件:jdk-7 ...

  3. 19 模块之shelve xml haslib configparser

    shelve 什么是shelve模块 也是一种序列化方式使用方法 1.opne 2.读写 3.close特点:使用方法比较简单 提供一个文件名字就可以开始读写 读写的方法和字典一致 你可以把它当成带有 ...

  4. 【转】Linux useradd

    Linux 系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统.用户的账号一方面可以帮助系统管理员对使用系统的用户进行 ...

  5. NCBI News

    NCBI淘汰序列GI - 使用Accession.Version代替! 截至2016年9月,被称为“GI”的整数序列标识符将不再包括在NCBI支持的序列记录的GenBank,GenPept和FASTA ...

  6. 2018.12.15 bzoj3998: [TJOI2015]弦论(后缀自动机)

    传送门 后缀自动机基础题. 求第kkk小的子串(有可能要求本质不同) 直接建出samsamsam,然后给每个状态赋值之后在上面贪心选最小的(过程可以类比主席树/平衡树的查询操作)即可. 代码: #in ...

  7. php Amome框架 层次设计备注

    层次说明: 每一级中函数都是为而且只为  上(高)一层  的文件服务的 最底层: AmemoMySql   基础数据库函数:AmemoConfig  数据库信息配置文件  再高一层: 一个文件对应一个 ...

  8. nginx自动启动脚本

    #!/bin/bash#nginx - this script starts and stops the nginx daemin # # chkconfig: - 85 15 # descripti ...

  9. excel2007自定义菜单项学习

    参考: http://club.excelhome.net/thread-1288002-1-1.html http://club.excelhome.net/thread-709306-1-1.ht ...

  10. 开机logo以及两种修改开机动画方法

    Android开机画面总共有三屏 一.第一屏:开机logo 1.选张png格式的图片,在Linux任意下执行(安装工具): sudo apt-get install pnmtoplainpm 2.在所 ...