线段树 25pts 求调,有注释
查看原帖
线段树 25pts 求调,有注释
583186
2c_s楼主2024/2/28 21:14

记录 link

tyuan 这次原味喝多少 lazytag

tre 这次热带风味喝多少 lazytag

yuan 最多连续喝了多少原味

re 最多连续喝了多少热带风味

myuan 最少连续喝了多少原味

mre 最少连续喝了多少热带风味

tag 击毁 lazytag

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll read(){
	ll k=0,flag=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')flag=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		k=(k<<1)+(k<<3)+(c^48);
		c=getchar();
	}
	return k*flag;
}
void print(ll x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)print(x/10);
    putchar(x%10+'0');
    return ;
}
const int N=2e5+10;
int n,q;
struct node{
    int l,r;
    ll sum,yuan,re,tyuan,tre,myuan,mre;
    bool tag;
}tr[N<<2];
void build(int i,int l,int r){
    tr[i].l=l;
    tr[i].r=r;
    tr[i].tyuan=tr[i].tre=1e18;//标记赋值
    if(l==r){
        tr[i].sum=1;//初始化个数
        return ;
    }
    int mid=l+r>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    tr[i].sum=tr[i<<1].sum+tr[i<<1|1].sum;
    return ;
}
void pushup(int i){
    tr[i].sum=tr[i<<1].sum+tr[i<<1|1].sum;
    tr[i].re=max(tr[i<<1].re,tr[i<<1|1].re);
    tr[i].mre=min(tr[i<<1].mre,tr[i<<1|1].mre);
    tr[i].yuan=max(tr[i<<1].yuan,tr[i<<1|1].yuan);
    tr[i].myuan=min(tr[i<<1].myuan,tr[i<<1|1].myuan);
    return ;
}
void pushdown(int i){
    if(tr[i].tag){//击毁了,所有变量清空
        tr[i<<1].tag=tr[i<<1|1].tag=1;
        tr[i<<1].sum=tr[i<<1|1].sum=0;
        
        tr[i<<1].myuan=tr[i<<1|1].myuan=0;
        tr[i<<1].yuan=tr[i<<1|1].yuan=0;

        tr[i<<1].mre=tr[i<<1|1].mre=0;
        tr[i<<1].re=tr[i<<1|1].re=0;
        
        tr[i<<1].tre=tr[i<<1|1].tre=1e18;
        tr[i<<1].tyuan=tr[i<<1|1].tyuan=1e18;

        tr[i].tag=0;
    }
    if(tr[i].tyuan!=1e18){//喝的原味,清空热带风味的变量,并处理原味的变量
        if(tr[i<<1].tyuan==1e18)tr[i<<1].tyuan=tr[i].tyuan;
        else tr[i<<1].tyuan+=tr[i].tyuan;

        if(tr[i<<1|1].tyuan==1e18)tr[i<<1|1].tyuan=tr[i].tyuan;
        else tr[i<<1|1].tyuan+=tr[i].tyuan;

        tr[i<<1].tre=tr[i<<1|1].tre=1e18;
        tr[i<<1].mre=tr[i<<1|1].mre=0;
        tr[i<<1].re=tr[i<<1|1].re=0;

        tr[i<<1].yuan+=tr[i].tyuan;
        tr[i<<1|1].yuan+=tr[i].tyuan;

        tr[i<<1].myuan+=tr[i].tyuan;
        tr[i<<1|1].myuan+=tr[i].tyuan;

        tr[i].tyuan=1e18;
    }
    if(tr[i].tre!=1e18){//喝的热带风味,与上面处理方式相反
        if(tr[i<<1].tre==1e18)tr[i<<1].tre=tr[i].tre;
        else tr[i<<1].tre+=tr[i].tre;

        if(tr[i<<1|1].tre==1e18)tr[i<<1|1].tre=tr[i].tre;
        else tr[i<<1|1].tre+=tr[i].tre;

        tr[i<<1].tyuan=tr[i<<1|1].tyuan=1e18;
        tr[i<<1].myuan=tr[i<<1|1].myuan=0;
        tr[i<<1].yuan=tr[i<<1|1].yuan=0;

        tr[i<<1].re+=tr[i].tre;
        tr[i<<1|1].re+=tr[i].tre;

        tr[i<<1].mre+=tr[i].tre;
        tr[i<<1|1].mre+=tr[i].tre;

        tr[i].tre=1e18;
    }
    return ;
}
void adyuan(int i,int l,int r,ll k){//和原味
    if(!tr[i].sum)return ;
    if(l<=tr[i].l&&tr[i].r<=r){
        tr[i].yuan+=k;
        tr[i].myuan+=k;
        if(tr[i].tyuan==1e18)tr[i].tyuan=k;
        else tr[i].tyuan+=k;
        tr[i].tre=1e18;
        tr[i].mre=tr[i].re=0;
        return ;
    }
    pushdown(i);
    int mid=tr[i].l+tr[i].r>>1;
    if(l<=mid)adyuan(i<<1,l,r,k);
    if(mid<r)adyuan(i<<1|1,l,r,k);
    pushup(i);
    return ;
}
void adre(int i,int l,int r,ll k){//喝热带风味
    if(!tr[i].sum)return ;
    if(l<=tr[i].l&&tr[i].r<=r){
        tr[i].re+=k;
        tr[i].mre+=k;
        if(tr[i].tre==1e18)tr[i].tre=k;
        else tr[i].tre+=k;
        tr[i].tyuan=1e18;
        tr[i].myuan=tr[i].yuan=0;
        return ;
    }
    pushdown(i);
    int mid=tr[i].l+tr[i].r>>1;
    if(l<=mid)adre(i<<1,l,r,k);
    if(mid<r)adre(i<<1|1,l,r,k);
    pushup(i);
    return ;
}
void del(int i,int l,int r,ll k){
    if(!tr[i].sum||tr[i].re<k&&tr[i].yuan<k)return ;//如果这一区间没有要删的就 return
    if(l<=tr[i].l&&tr[i].r<=r){
        if(tr[i].mre>=k||tr[i].myuan>=k){//符合要求就删除
            tr[i].yuan=tr[i].re=tr[i].mre=tr[i].myuan=tr[i].sum=0;
            tr[i].tyuan=tr[i].tre=1e18;
            tr[i].tag=1;
            return ;
        }
        if(tr[i].l==tr[i].r)return ;
        pushdown(i);//先 pushdown 一遍
        del(i<<1,l,r,k);//区间不全符合要求,那么向左右分别递归
        del(i<<1|1,l,r,k);
    }
    pushdown(i);
    int mid=tr[i].l+tr[i].r>>1;
    if(l<=mid)del(i<<1,l,r,k);
    if(mid<r)del(i<<1|1,l,r,k);
    pushup(i);
    return ;
}
int main(){
    cin>>n>>q;
    build(1,1,n);
    while(q--){
        int op=read();
        if(op==1){
            int l=read(),r=read();
            ll k=read();
            adyuan(1,l,r,k);
            if(l>1)adre(1,1,l-1,k);
            if(r<n)adre(1,r+1,n,k);
        }
        if(op==2){
            int l=read(),r=read();
            ll k=read();
            del(1,l,r,k);
        }
        if(op==3){
            print(tr[1].sum);
            puts("");
        }
    }
	return 0;
}
2024/2/28 21:14
加载中...