zoukankan      html  css  js  c++  java
  • 线段树区间取反

    题目描述

    现有N(2 ≤ N ≤ 100000)盏灯排成一排,从左到右依次编号为:1,2,......,N。然后依次执行M(1 ≤ M ≤ 100000)项操作,操作分为两种:第一种操作指定一个区间[a, b],然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开),第二种操作是指定一个区间[a, b],要求你输出这个区间内有多少盏灯是打开的。灯在初始时都是关着的。

    输入输出格式

    输入格式:

    第一行有两个整数N和M,分别表示灯的数目和操作的数目。接下来有M行,每行有三个整数,依次为:c, a, b。其中c表示操作的种类,当c的值为0时,表示是第一种操作。当c的值为1时表示是第二种操作。a和b则分别表示了操作区间的左右边界(1 ≤ a ≤ b ≤ N)。

    输出格式:

    每当遇到第二种操作时,输出一行,包含一个整数:此时在查询的区间中打开的灯的数目。

    输入输出样例

    输入样例#1
    4 5
    0 1 2
    0 2 4
    1 2 3
    0 2 4
    1 1 4
    
    输出样例#1
    1
    2



    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define ls(x) (x<<1)
    #define rs(x) (ls(x)|1)
    const int maxn=1e5+5;
    struct FFF{
        int l,r;
        int op;
    	int cl;
    	bool rev;
        int mid(){return l+r>>1;}
        int len(){return r-l+1;}
    }t[maxn<<2];
    int n,m;
    void up(int o){
    	t[o].op=t[ls(o)].op+t[rs(o)].op;
    	t[o].cl=t[ls(o)].cl+t[rs(o)].cl;
    }
    void build(int l=1,int r=n,int o=1){
        t[o].l=l;t[o].r=r;
    	t[o].op=0;
        if(l==r){
            t[o].cl=1;
            return;
        }
        int mid=l+r>>1;
        build(l,mid,ls(o));
        build(mid+1,r,rs(o));
        up(o);
    }
    void down(int o){
        if(t[o].rev){
    		for(int i=0;i<=1;++i){
    			t[ls(o)|i].rev^=1;
    			swap(t[ls(o)|i].op,t[ls(o)|i].cl);
    		}
    		t[o].rev=0;
    	}
    }
    void add(int l,int r,int o=1){
        if(l<=t[o].l&&t[o].r<=r){
            t[o].rev^=1;
    		swap(t[o].op,t[o].cl);
            return;
        }
        int mid=t[o].mid();
        down(o);
        if(l<=mid)add(l,r,ls(o));
        if(r>mid)add(l,r,rs(o));
        up(o);
    }
    int getsum(int l,int r,int o=1){
        if(l<=t[o].l&&t[o].r<=r){
            return t[o].op;
        }
        int ans=0;
        int mid=t[o].mid();
        down(o);
        if(l<=mid)ans+=getsum(l,r,ls(o));
        if(r>mid)ans+=getsum(l,r,rs(o));
        return ans;
    }
    signed main(){
        cin>>n>>m;
    	build();
    	while(m--){
    		int op,l,r;
    		cin>>op>>l>>r;
    		if(op==0){
    			add(l,r);
    		}
    		if(op==1){
    			cout<<getsum(l,r)<<endl;
    		}
    	}
        return 0;
    }
    

      

  • 相关阅读:
    GPT分区安装windows10详细教程
    paddle07-paddle.regularizer正则化
    paddle02-paddle.io(数据读取相关) 【完】
    【python】80行代码实现压缩包密码破解软件,支持zip和rar
    【python】B站弹幕数据分析及可视化(爬虫+数据挖掘)
    【python】10行代码下载B站弹幕
    【pytorch】使用迁移学习(resnet18)训练mnist数据集
    迁移学习在实际应用中需要注意什么?
    【python】进度条的简单实现
    【机器学习】AI去马赛克工具(图像修复)
  • 原文地址:https://www.cnblogs.com/eric-walker/p/9425376.html
Copyright © 2011-2022 走看看