刷到了进阶指南题单数据结构的练习部分,是对之前的知识的巩固提升,一步步写过来真的很难受,归根结底还是自己太菜了/(ㄒoㄒ)/~~
这次的题目主要考察线段树lazy和对结构体元素的建立,果然,仅仅会一个线段树是远远不够的,最重要的是他的变形。这一题我刚开始就没想出来怎么设置元素来实现功能,但是看了别人的代码之后恍然大悟,原来就是前面的题目相似的设置方式,只是加上Lazy之后变得稍微复杂了,亏我自己还憨憨地写了线段树却完全用不上...
https://www.acwing.com/activity/content/code/content/77313/
思路:元素中设置num,len,lmax,rmax,lazy五个元素,分别储存当前节点存在的最大连续空间,节点总长度,左节点最大空间,右节点最大空间和延迟标记,其中lazy为1时表示被占用了,为2时表示要清空。这样子通过pushdown,pushup两个函数简化了很多步骤,详见代码,线段树在高手手中真是有无数可能...
#include <bits/stdc++.h> using namespace std; #define Lson(rt) rt<<1,l,mid #define Rson(rt) rt<<1 | 1,mid+1,r //用宏定义方便后面的就很舒服 const int N=5e5+200; int n,m; struct Segment_Tree { int sum,len,lmax,rmax,lazy; } t[4*N]; void build(int rt,int l,int r) { t[rt].lazy=0; t[rt].sum=t[rt].len=t[rt].lmax=t[rt].rmax=r-l+1; if(l==r) return; int mid=(l+r)/2; build(Lson(rt)); build(Rson(rt)); } void Push_down(int rt)
//向下传递的函数 { if(t[rt].lazy==0) return; if(t[rt].lazy==1)
//这个时候表示节点空间被占用了... { t[rt*2].lazy=t[rt*2+1].lazy=1; t[rt*2].sum=t[rt*2].lmax=t[rt*2].rmax=0; t[rt*2+1].sum=t[rt*2+1].lmax=t[rt*2+1].rmax=0;
//被占用之后要记得更新子节点的数值 } if(t[rt].lazy==2)
//表示房子被清空,同样要更新数值 { t[rt*2].lazy=t[rt*2+1].lazy=2; t[rt*2].sum=t[rt*2].lmax=t[rt*2].rmax=t[rt*2].len; t[rt*2+1].sum=t[rt*2+1].lmax=t[rt*2+1].rmax=t[rt*2+1].len;
//返回成原来值 } t[rt].lazy=0; } void Push_up(int rt) { if(t[rt*2].sum==t[rt*2].len) t[rt].lmax=t[rt*2].len+t[rt*2+1].lmax; else t[rt].lmax=t[rt*2].lmax; if(t[rt*2+1].sum==t[rt*2+1].len) t[rt].rmax=t[rt*2+1].len+t[rt*2].rmax; else t[rt].rmax=t[rt*2+1].rmax; t[rt].sum=max(max(t[rt*2].sum,t[rt*2+1].sum),t[rt*2].rmax+t[rt*2+1].lmax); } void change(int rt,int l,int r,int tag,int L,int R) { Push_down(rt); if(L<=l&&r<=R) { if(tag==1) t[rt].sum=t[rt].lmax=t[rt].rmax=0; else t[rt].sum=t[rt].lmax=t[rt].rmax=t[rt].len; t[rt].lazy=tag; return; } int mid=(l+r)/2; if(L<=mid) change(Lson(rt),tag,L,R); if(R>mid) change(Rson(rt),tag,L,R); Push_up(rt); } int Query(int rt,int l,int r,int len) { Push_down(rt); if(l==r) return l; int mid=(l+r)/2; if(t[rt*2].sum>=len) return Query(rt*2,l,mid,len); if(t[rt*2].rmax+t[rt*2+1].lmax>=len) return mid-t[rt*2].rmax+1; else return Query(rt*2+1,mid+1,r,len); } int main() { scanf("%d%d",&n,&m); build(1,1,n); for(int i=1; i<=m; i++) { int ts,x,y; scanf("%d",&ts); if(ts==1) { scanf("%d",&x); if(t[1].sum>=x) { int left=Query(1,1,n,x); printf("%d\n",left); change(1,1,n,1,left,left+x-1); } else printf("0\n"); } else { scanf("%d%d",&x,&y); change(1,1,n,2,x,x+y-1); } } return 0; }