Codeforces Beta Round #75 (Div. 1 Only) B. Queue 线段树。单点更新

http://codeforces.com/problemset/problem/91/B

题意:

给你n个数,求得i 到n中小于a[i]的最右边的a[j],然后求a[i]到a[j]之间包含了多少个数。

思路:

首先自己在做这道题的时候没有认真读题,直接把题意搞成求得i 到n中小于a[i]的最右边的a[j],然后求a[i]到a[j]之间包含了多少个小于a[i]的数了。。。结果样例都没过。唉自己还是太粗心,一定要认真把题意搞清楚,然后把想法想好了再敲。不过也算是做了另一道题目吧。

首先我的思路,好像比较复杂。 我们利用线段树维护小于a[i]的区间[1,a[i]]的最大坐标值,当然要将数列离散话,因为a[i]最大为10^9 而n最大是10^5 .每次插入数据更新区间最值,然后就是求出该区间最值与当前坐标比较求个数。

View Code
By E_star, contest: Codeforces Beta Round #75 (Div. 1 Only), problem: (B) Queue, Accepted, #
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a,b) (a) > (b)? (b):(a)
#define Max(a,b) (a) > (b)? (a):(b)

#define ll long long
#define inf 0x7f7f7f7f
#define MOD 1073741824
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 1000007
#define N 1000007
using namespace std;
//freopen("data.in","r",stdin);

struct node{
    int val;
    int pos;
}a[N];
int X[N];
int val[N*4];
int pos[N];

void pushup(int rt){
    val[rt] = max(val[rt<<1],val[rt<<1|1]);
}
void update(int pos,int sc,int l,int r,int rt){
    if (l == r){
        val[rt] = sc;
        return ;
    }
    int m = (l + r)>>1;
    if (pos <= m) update(pos,sc,lc);
    else update(pos,sc,rc);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
    if (l >= L && r <= R){
        return val[rt];
    }
    int res = 0;
    int m = (l + r)>>1;
    if (L <= m) res = max(res,query(L,R,lc));
    if (R > m) res = max(res,query(L,R,rc));
    return res;
}
int bSearch(int p,int L,int R){
    int l = L;
    int r = R;
    int ans = 0;
    while (l <= r){
        int m = (l + r)>>1;
        if (X[m] <= p){
            l = m + 1;
            ans = m;
        }
        else{
            r = m  - 1;
        }
        //puts("<<<<");
    }
    return ans;
}

int main(){
    //freopen("data.in","r",stdin);
    int i;
    int n;
    while (~scanf("%d",&n)){
        for (i = 1; i <= n; ++i){
            scanf("%d",&a[i].val);
            a[i].pos = i;
            X[i] = a[i].val;
        }
       //离散化
        sort(X + 1,X + 1 + n);
        int k = 1;
        for (i = 2; i <= n; ++i){
            if (X[i] != X[i - 1]) X[++k] = X[i];
        }
        //每插进一个点就更新[1,a[i]]区间最值
        CL(val,0);
        for (i = 1; i <= n; ++i){
            pos[i] = bSearch(a[i].val,1,k);
            update(pos[i],a[i].pos,1,k,1);
        }
       
        for (i = 1; i < n; ++i){
            int p = bSearch(a[i].val - 1,1,k);//二分查找第一个小于a[i]的值
            if (p == 0){
                printf("-1 ");
                continue;
            }
            int ans = query(1,p,1,k,1);//询问该区间的最大坐标
            if (ans <= a[i].pos) printf("-1 ");
            else{
                ans = ans - a[i].pos - 1;
                printf("%d ",ans);
            }
        }
        printf("-1\n");
    }
    return 0;
}     

 

别人的思路,思考方向不一样,做法就不一样。我觉得这个想法很简洁明了。他直接记录区间最值,枚举每个a[i]每次把枚举到的a[i]更新成inf,线段树求出整个区间最小值,与该值比较,如果大于等于它肯定输出-1,否则线段树里求右边第一个小于a[i]的值的坐标。 (这里最巧妙数的求最右边第一个小于a[i]的坐标,以前没接触过这个求法)

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a,b) (a) > (b)? (b):(a)
#define Max(a,b) (a) > (b)? (a):(b)

#define ll long long
#define inf 0x7f7f7f7f
#define MOD 1073741824
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 1000007
#define N 1000007
using namespace std;
//freopen("data.in","r",stdin);

int a[N],val[N];

void pushup(int rt){
    val[rt] = min(val[rt<<1],val[rt<<1|1]);
}
void build(int l,int r,int rt){
    if (l == r){
        scanf("%d",&val[rt]);
        a[l] = val[rt];
        return ;
    }
    int m = (l + r)>>1;
    build(lc);
    build(rc);
    pushup(rt);
}
void update(int pos,int l,int r,int rt){
    if (l == r){
        val[rt] = inf;
        return ;
    }
    int m = (l + r)>>1;
    if (pos <= m) update(pos,lc);
    else update(pos,rc);
    pushup(rt);
}
int query(int sc,int l,int r,int rt){
    if (l == r) return l;
    int m = (l + r)>>1;
    if (val[rt<<1|1] < sc) return query(sc,rc);
    else return query(sc,lc);
}
int main(){
    //freopen("data.in","r",stdin);
    int i;
    int n;
    while (~scanf("%d",&n)){
        build(1,n,1);
        for (i = 1; i <= n; ++i){
            update(i,1,n,1);
            if (val[1] >= a[i]){
                printf("-1%c",i == n ? '\n' : ' ');
            }
            else{
                int pos = query(a[i],1,n,1);
                printf("%d%c",pos - i - 1,i == n ?  '\n' : ' ');
            }
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/E-star/archive/2012/10/23/2736202.html

# 高校智慧校园解决方案摘要 智慧校园解决方案是针对高校信息化建设的核心工程,旨在通过物联网技术实现数字化校园的智能化升级。该方案通过融合计算机技术、网络通信技术、数据库技术和IC卡识别技术,初步实现了校园一卡通系统,进而通过人脸识别技术实现了更精准的校园安全管理、生活管理、教务管理和资源管理。 方案包括多个管理系统:智慧校园管理平台、一卡通卡务管理系统、一卡通人脸库管理平台、智能人脸识别消费管理系统、疫情防控管理系统、人脸识别无感识别管理系统、会议签到管理系统、人脸识别通道管理系统和图书馆对接管理系统。这些系统共同构成了智慧校园的信息化基础,通过统一数据库和操作平台,实现了数据共享和信息一致性。 智能人脸识别消费管理系统通过人脸识别终端,在无需接触的情况下快速完成消费支付过程,提升了校园服务效率。疫情防控管理系统利用热成像测温技术、视频智能分析等手段,实现了对校园人员体温监测和疫情信息实时上报,提高了校园公共卫生事件的预防和控制能力。 会议签到管理系统和人脸识别通道管理系统均基于人脸识别技术,实现了会议的快速签到和图书馆等场所的高效通行管理。与图书馆对接管理系统实现了一卡通系统与图书馆管理系统的无缝集成,提升了图书借阅的便捷性。 总体而言,该智慧校园解决方案通过集成的信息化管理系统,提升了校园管理的智能化水平,优化了校园生活体验,增强了校园安全,并提高了教学和科研的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值