其他分享
首页 > 其他分享> > [解题记录] P2894 [USACO08FEB]Hotel G

[解题记录] P2894 [USACO08FEB]Hotel G

作者:互联网

P2894 [USACO08FEB]Hotel G

题意简述

  1. 输入一个数 \(x\) ,在 \([1,n]\) 中找满足长度为 \(x\) 的最左边的全是 \(0\) 区间,输出左端点并将这个区间全部赋值为 \(1\),如果找不到则输出 \(0\)

  2. 输入两个数 \(x,y\) ,将区间 \([x,x+y-1]\) 里的数全部赋值为 \(0\)


解题思路

属于是线段树好题了属于是

题目要求我们找 \(0\) 区间(全是 \(0\) 的区间,自己乱定义的),所以我们就可以用线段树去维护区间内最大的 \(0\) 区间,为了更好的

pushup ,沿用最大子段和的思路,同时维护以左,右为端点的区间最大 \(0\) 区间

对于操作 \(1\) ,我们只要判断一下 \([1,n]\) 范围里有没有满足的,如果没有就是无解,然后以先左后中最后右的方法进行查询,要注意查到了

就直接 \(return\) ,然后把这个区间全部改为 \(0\)

对于操作 \(2\),其实就是把我们维护的东西的值全部改为区间长度(所以我们还要维护一个 \(sum\) )


\(Code\)

#include <bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
#define int long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}
const int N=5e4+10;
struct node{
    int dat;//最大0区间
    int sum;//区间长度
    int lmax,rmax;//以左/右为端点的最大0区间
    int lazy;
}tree[N*4];
int m,mod,n;
void pushup(int p){
    tree[p].sum=tree[ls].sum+tree[rs].sum;
    if(tree[ls].dat==tree[ls].sum) tree[p].lmax=tree[ls].sum+tree[rs].lmax;
    else tree[p].lmax=tree[ls].lmax;
    if(tree[rs].dat==tree[rs].sum) tree[p].rmax=tree[rs].sum+tree[ls].rmax;
    else tree[p].rmax=tree[rs].rmax;
    tree[p].dat=max(tree[ls].dat,max(tree[rs].dat,tree[ls].rmax+tree[rs].lmax));
}
void pushdown(int p){
    if(tree[p].lazy==0) return;
    if(tree[p].lazy==1){
	tree[ls].lazy=tree[rs].lazy=1;
	tree[ls].lmax=tree[ls].rmax=tree[ls].dat=0;
	tree[rs].lmax=tree[rs].rmax=tree[rs].dat=0;
    }
    if(tree[p].lazy==2){
	tree[ls].lazy=tree[rs].lazy=2;
	tree[ls].lmax=tree[ls].rmax=tree[ls].dat=tree[ls].sum;
	tree[rs].lmax=tree[rs].rmax=tree[rs].dat=tree[rs].sum;
    }
    tree[p].lazy=0;
}
void build(int p,int l,int r){
    if(l==r){
	tree[p].dat=tree[p].sum=tree[p].lmax=tree[p].rmax=1;
	return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(p);
}
void upd(int p,int l,int r,int x,int y,int k){
    if(x<=l&&y>=r){
	if(k==1) tree[p].lmax=tree[p].rmax=tree[p].dat=0;
	else tree[p].lmax=tree[p].rmax=tree[p].dat=tree[p].sum;
	tree[p].lazy=k;
	return;
    }
    pushdown(p);
    int mid=(l+r)>>1;
    if(x<=mid) upd(ls,l,mid,x,y,k);
    if(y>mid) upd(rs,mid+1,r,x,y,k);
    pushup(p);
}
int query(int p,int l,int r,int x){
    if(l==r) return l;
    pushdown(p);
    int mid=(l+r)>>1;
    if(tree[ls].dat>=x) return query(ls,l,mid,x);
    if(tree[ls].rmax+tree[rs].lmax>=x) return mid-tree[ls].rmax+1;
    else return query(rs,mid+1,r,x);
}
signed main(){
    n=read();m=read();
    build(1,1,n);
    for(int i=1;i<=m;++i){
	int op=read();
	if(op==1){
	    int x=read();
	    if(tree[1].dat>=x){
		int left=query(1,1,n,x);
		printf("%lld\n",left);
		upd(1,1,n,left,left+x-1,1);
	    }
	    else  puts("0");
	}
	else{
	    int x,y;
	    x=read();y=read();
	    upd(1,1,n,x,x+y-1,2);
	}
    }
    return 0;
}


\(Experience\)

upd函数里的整个区间都包括的 \(return\) 一定要打

懒标记可以同时维护在多种操作上

标签:return,int,Hotel,tree,mid,USACO08FEB,区间,ls,P2894
来源: https://www.cnblogs.com/hhhd-/p/15834317.html