zoukankan      html  css  js  c++  java
  • 线段树单点更新解插空问题

    poj2828

    线段树维护区间空余的位置,每次插入一个点

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define maxn 200020
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    struct node{
        int pos,w,id;
    }nodes[maxn];
    int sum[maxn<<2];
    int ans[maxn];//用来存储
    void pushUP(int rt){
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void build(int l,int r,int rt){
        if(l==r){
            sum[rt]=1;
            return;
        }
        int m=l+r>>1;
        build(lson);
        build(rson);
        pushUP(rt);
    }
    void update(int i,int pos,int l,int r,int rt){
        if(l==r){
            ans[l]=nodes[i].w;
            sum[rt]--;
            return;
        }
        sum[rt]--;
        int m=l+r>>1;
        if(pos<=sum[rt<<1])
            update(i,pos,lson);
        else 
            update(i,pos-sum[rt<<1],rson);
    }
    int main(){
        int n;
        while(scanf("%d",&n)==1){
            memset(ans,0,sizeof ans);
            for(int i=1;i<=n;i++)
                scanf("%d%d",&nodes[i].pos,&nodes[i].w),nodes[i].pos++;
            build(1,n,1);
            for(int i=n;i>=1;i--)
                update(i,nodes[i].pos,1,n,1);//倒着把i个插队更新到线段树里
            for(int i=1;i<=n;i++)
                printf("%d ",ans[i]);
            puts("");
        }
    }

    hdu3564 线段树解决插值,求出最终序列,再求lis

    /*
    给出n个数字,依次分别是[1,n]
    每次给定第i个数字的插入点【0,n-1],求lis
    
    离线+线段树+lis
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 1000005
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    int sum[maxn<<2];//存储当前位置有多少空位
    int ans[maxn];//ans[i]表示i在位置ans[i]
    int op[maxn];
    int dp[maxn];
    void build(int l,int r,int rt){
        if(l==r){
            sum[rt]=1;
            return;
        }
        int m=l+r>>1;
        build(lson);
        build(rson);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void update(int pos,int val,int l,int r,int rt){
        if(l==r){
            sum[pos]=0;
            ans[val]=l;//val被放在了位置l
            return;
        }
        sum[pos]--;
        int m=l+r>>1;
        if(pos<=sum[rt<<1]) update(pos,val,lson);
        else update(pos-sum[rt<<1],val,rson);
    }
    int main(){
        int n,T;
        cin >> T;
        for(int tt=1;tt<=T;tt++){
            memset(sum,0,sizeof sum);
            memset(ans,0,sizeof ans);
            memset(op,0,sizeof op);
            
            printf("Case #%d:
    ",tt);
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d",&op[i]),op[i]++;
            build(1,n,1);//从0开始建立线段树
            for(int i=n;i>=1;i--)
                update(op[i],i,1,n,1);//把i插到op[i]及其以后位置,ans[i]维护i的位置
            
            //第一次插入1,第二次插入2,第三次插入3...其位置被保存在ans[1],ans[2],ans[3]...
            //要求每次插入后的lis,因为可以保证每次插入的数字比之前的大,所以只要插入的位置比之前数字的位置大就能保证lis,等价于求ans[i]的lis
            //求lis,每次找到第一个比ans[i]大的,将其替换成ans[i]
            memset(dp,0,sizeof dp);
            int len=0;
            for(int i=1;i<=n;i++){
                int k=lower_bound(dp+1,dp+1+len,ans[i])-dp;
                len=max(len,k);
                dp[k]=ans[i];
                printf("%d
    ",len);
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    现代操作系统:原理与实现配套实验ChCorelab02
    损失函数:交叉熵
    什么是 AWS IoT Greengrass?
    softmax与sigmoid的关系&最大熵与极大似然估计的关系
    AWS IoT Greengrass:连接器入门
    损失函数:最小二乘法与极大似然估计法
    AWS IoT Greengrass:将密钥部署到核心
    奇异值分解(SVD)
    积性函数前缀和个人总结
    AWS IoT Greengrass:核心软件的 OTA 更新
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9898864.html
Copyright © 2011-2022 走看看