玲珑杯” Round #19 Buildings 【线段树+尺取法】+【vector + 尺取法】

来源:互联网 发布:mac系统误删文件 编辑:程序博客网 时间:2024/06/05 14:42

这里写图片描述

第一种 线段树(维护区间的最大值和最小值)+尺取法

#include<bits/stdc++.h>#define LL long long#define lele  o<<1#define riri  o<<1|1#define lson o<<1,le,mid#define rson o<<1|1,mid+1,riusing namespace std;const int MAXN =2*1e5+10;struct Tree{    int l,r;    int maxx;    int minn;}tree[MAXN<<2];int n,k;void pushup(int o){    tree[o].maxx=max(tree[lele].maxx,tree[riri].maxx);    tree[o].minn=min(tree[lele].minn,tree[riri].minn);}void build(int o,int le,int ri){    tree[o].l=le;tree[o].r=ri;    if(le==ri) {        int val;scanf("%d",&val);        tree[o].maxx=tree[o].minn=val;        return ;    }    int mid =(le+ri)>>1;    build(lson);    build(rson);    pushup(o);} int querymax(int o,int le,int ri)   {    if(le<=tree[o].l&&ri>=tree[o].r)    return tree[o].maxx;    int mid=(tree[o].l+tree[o].r)>>1;    if(ri<=mid) querymax(lele,le,ri);    else if(le>mid ) querymax(riri,le,ri);    else  return max(querymax(lele,le,mid),querymax(riri,mid+1,ri)); } int querymin(int o,int le,int ri)   {    if(le<=tree[o].l&&ri>=tree[o].r)    return tree[o].minn;    int mid=(tree[o].l+tree[o].r)>>1;    if(ri<=mid) querymin(lele,le,ri);    else if(le>mid ) querymin(riri,le,ri);    else  return min(querymin(lele,le,mid),querymin(riri,mid+1,ri)); }int main(){    while(scanf("%d%d",&n,&k)!=EOF){        build(1,1,n);        int le=1;int ri=1;        LL sum=0;        for(;ri<=n&&le<n;){ // 尺取法            while((querymax(1,le,ri)-querymin(1,le,ri))>k)  le++;              sum+=(LL)(ri-le);  ri++;         }        printf("%lld\n",sum+n);    }    return 0;}

分析 二
可以用vector来维护区间的有序性,从而找到最大值和最小值,从而尺取法解。
代码

#include<bits/stdc++.h>#define LL long longusing namespace std;const int MAXN =1e6+100;int arr[MAXN];vector<int>ve;int main(){    int n,k;    while(scanf("%d%d",&n,&k)!=EOF){        ve.clear();        for(int i=1;i<=n;i++) scanf("%d",&arr[i]);        if(n==1) {puts("1");continue;}    int le,ri; le=ri=1;  ve.push_back(arr[1]);    int siz=1; LL sum=0;        for(int i=2;i<=n;i++){            ri=i;            int ans=lower_bound(ve.begin(),ve.end(),arr[ri])-ve.begin();            ve.insert(ve.begin()+ans,arr[ri]); siz++;            while(ve[siz-1]-ve[0]>k){                ans=lower_bound(ve.begin(),ve.end(),arr[le++])-ve.begin();                ve.erase(ve.begin()+ans); siz--;            }            sum+=(LL)(ri-le); //如果(max-min)<=k 那么max和区间里的所有值的差肯定也都小于等于k        }    printf("%lld\n",sum+n);  //最后加上自身的区间一定是小于等于k的     }    return 0;}
原创粉丝点击