当前位置:编程学习 > C/C++ >>

POJ 2828

题意:
给出一个N,接下来是N个数,每个数有一个插入的位置。
输出最后的顺序。
思路:
一开始以为就是链表插入,然后看了下数据量。就没想法了。
就用了线段树,建树和询问都是很基础的东西,就是最后处理位置有一些技巧。
[cpp] 
#include <iostream> 
#include <cstdio> 
#include <algorithm> 
#include <string> 
#include <cmath> 
#include <cstring> 
#include <queue> 
#include <set> 
#include <vector> 
#include <stack> 
#include <map> 
#include <iomanip> 
#define PI acos(-1.0) 
#define Max 200005 
#define inf 1<<28 
#define LL(x) (x<<1) 
#define RR(x)(x<<1|1) 
using namespace std; 
 
int n; 
struct kdq 

    int l, r; 
    int num; 
} tree[Max*4]; 
int pos[Max],num[Max]; 
int newpos[Max];//记录插入后的新地址 
void build_tree(int l,int r,int u) 

    tree[u].l=l; 
    tree[u].r=r; 
    tree[u].num=r-l+1; 
    if(l==r)return ; 
    int mid=(l+r)>>1; 
    build_tree(l,mid,LL(u)); 
    build_tree(mid+1,r,RR(u)); 

int query(int id,int u) 

    tree[u].num--;//每次插入,则区间值递减 
    if(tree[u].l==tree[u].r) 
        return tree[u].l; 
    if(tree[LL(u)].num>=id)//尽量往左边插入 
        return query(id,LL(u)); 
    else 
        return query(id-tree[LL(u)].num,RR(u)); 

int main() 

    int i,j,k,l,m; 
    while(~scanf("%d",&n)) 
    { 
        for(i=1; i<=n; i++) 
        { 
            scanf("%d%d",&pos[i],&num[i]); 
            pos[i]++; 
        } 
        build_tree(1,n,1); 
        for(i=n; i>=1; i--) 
            newpos[query(pos[i],1)]=i;//反向插入。假设pos[n]和pos[n-1]相等,那么第n个数肯定在第n-1个数之前,因为后插入。 
            //所以这里直接从n到1进行插入,一遍插入结束之后就是新的位置,如果从前往后插入,还得考虑相同的位置进行移位 
        for(i=1; i<=n; i++) 
            printf("%d ",num[newpos[i]]);//最后直接输出各自的新位置 
        printf("\n"); 
    } 
    return 0; 

 

 


补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,