bzoj1593(线段树)

来源:互联网 发布:指针数组初始化 null 编辑:程序博客网 时间:2024/05/29 14:37

线段树一种新见的询问方式。

1.询问连续长度为x的空的区间的最左端点,并将这段覆盖

(通过最长子序列来做,先判断左边有没有这样的区间,再判断相连接的地方有没有,再判断右边有没有)

2.区间覆盖为空或有 

 

#include<cstdio>#include<cmath>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;int n,ans;struct aa{int l,r,mx,qz,hz,bj;}a[50005*4];void up(int i){int l=i<<1,r=i<<1|1;a[i].mx=max(a[l].mx,a[r].mx);a[i].mx=max(a[i].mx,a[l].hz+a[r].qz);if (a[l].qz==a[l].r-a[l].l+1) a[i].qz=a[l].qz+a[r].qz;else a[i].qz=a[l].qz;if (a[r].hz==a[r].r-a[r].l+1) a[i].hz=a[r].hz+a[l].hz;else a[i].hz=a[r].hz;}void down(int i){if (a[i].bj>=0){int k=a[i].bj;a[i].bj=-1;a[i<<1].bj=a[i<<1|1].bj=k;if (a[i<<1].l)a[i<<1].mx=a[i<<1].qz=a[i<<1].hz=k?0:a[i<<1].r-a[i<<1].l+1;if (a[i<<1|1].l)a[i<<1|1].mx=a[i<<1|1].qz=a[i<<1|1].hz=k?0:a[i<<1|1].r-a[i<<1|1].l+1;}}void build(int i,int l,int r){a[i].l=l;a[i].r=r;a[i].bj=-1;if (l==r){a[i].qz=a[i].hz=a[i].mx=1;return ;}int mid=(l+r)>>1;build(i<<1,l,mid);build(i<<1|1,mid+1,r);up(i);}void updata(int i,int l,int r,int k){if (a[i].l==l&&a[i].r==r) {a[i].bj=k;a[i].mx=a[i].qz=a[i].hz= k ? 0:a[i].r-a[i].l+1;return ;}down(i);int mid=(a[i].l+a[i].r)>>1;if (r<=mid) updata(i<<1,l,r,k);else if (l>mid) updata(i<<1|1,l,r,k);else updata(i<<1,l,mid,k),updata(i<<1|1,mid+1,r,k);up(i);}int fin(int i,int d){down(i);if (a[i].r-a[i].l+1==d&&a[i].mx==d) return a[i].l;if (a[i<<1].mx>=d) return fin(i<<1,d);if (a[i<<1].hz+a[i<<1|1].qz>=d) return a[i<<1].r-a[i<<1].hz+1;if (a[i<<1|1].mx>=d) return fin(i<<1|1,d);return 0;}int main(){int m,op,x,d;scanf("%d%d",&n,&m);build(1,1,n);while (m--){scanf("%d",&op);if (op==1) {scanf("%d",&d);ans=fin(1,d);printf("%d\n",ans);if(ans) updata(1,ans,ans+d-1,1);}else {scanf("%d%d",&x,&d);updata(1,x,x+d-1,0);}}return 0;}


总结:

1:虽然变了形式,但是还是可以在线段树的优化的类型之内的,其实只要是用线段树可以优化到log (n)级别的,一般都可以考虑线段树,实际上这也不是一个很固定的东西,完全可以在理性的基础上发挥自己的创造力,尽量将线段树真正做到灵活。将线段树灵活变通,以便在其他的问题当中作为一种数据结构的优化,会大大提高效率。

0 0
原创粉丝点击