zoukankan      html  css  js  c++  java
  • P3870 [TJOI2009]开关

    题目描述

    现有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

    Solution:

      本题裸的线段树模板~~。

      对于每次修改取反,直接修改一下懒惰标记(改为$Xor;1$),并对区间和取反(即$sum[rt]=(r-l+1)-sum[rt]$),意味着原来的$0$的个数就是修改后区间中的$1$的个数。

      然后就是简单的区间修改区间求和拉~。

    代码: 

    #include<bits/stdc++.h>
    #define il inline
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    using namespace std;
    const int N=1e5+5;
    int n,m,sum[N<<2],lazy[N<<2];
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    il void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
    il void pushdown(int rt,int k){
        if(lazy[rt]){
            lazy[rt<<1]^=1;
            lazy[rt<<1|1]^=1;
            sum[rt<<1]=(k-(k>>1))-sum[rt<<1];
            sum[rt<<1|1]=(k>>1)-sum[rt<<1|1];
            lazy[rt]=0;
        }
    }
    il void update(int L,int R,int c,int l,int r,int rt){
        if(L<=l&&R>=r){lazy[rt]^=1;sum[rt]=(r-l+1)-sum[rt];return;}
        pushdown(rt,r-l+1);
        int m=l+r>>1;
        if(L<=m)update(L,R,c,lson);
        if(m<R)update(L,R,c,rson);
        pushup(rt);
    }
    il int query(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r){return sum[rt];}
        pushdown(rt,r-l+1);
        int m=l+r>>1,ret=0;
        if(L<=m)ret+=query(L,R,lson);
        if(m<R)ret+=query(L,R,rson);
        return ret;
    }
    int main(){
        n=gi(),m=gi();
        int x,y,z;
        while(m--){
            x=gi(),y=gi(),z=gi();
            if(!x)update(y,z,1,1,n,1);
            else printf("%d
    ",query(y,z,1,n,1));
        }
        return 0;
    }

     

  • 相关阅读:
    Fiddler抓包
    用powershell Crescendo模块,把【linux字符命令】包装成【powershell对象命令】
    初探设计模式-单例模式
    dev的CheckedListBoxControl的使用
    git的安装及使用(三)----SSH连接
    go——杂碎小知识
    goland安装+打印hello world
    git的安装及使用(二)
    git的安装及使用(一)
    xxx
  • 原文地址:https://www.cnblogs.com/five20/p/9033185.html
Copyright © 2011-2022 走看看