• 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

    可以用异或 见代码
    因为一开始亮的灯数为0 所以不用build
    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    #define lson l,m,pos<<1
    #define rson m+1,r,pos<<1|1
    const int N=100000+5;
    ll sum[N<<2],col[N<<2];
    
    void up(int pos)
    {
        sum[pos]=sum[pos<<1]+sum[pos<<1|1];
    }
    void down(int pos,int m)
    {
        if(col[pos])
        {
            col[pos<<1]^=1;//每个下传懒标记进行异或   因为负负得正
            col[pos<<1|1]^=1;
            sum[pos<<1]=(m-(m>>1))-sum[pos<<1];//正常修改
            sum[pos<<1|1]=(m>>1)-sum[pos<<1|1];
            col[pos]=0;
        }
    }
    void update(int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)
        {
            col[pos]^=1;//不能改成1! 
            sum[pos]=r-l+1-sum[pos];
            return ;
        }
        int m=(l+r)>>1;
        down(pos,r-l+1);
        if(L<=m)
            update(L,R,lson);
        if(R>m)
            update(L,R,rson);
        up(pos);
    }
    int query(int L,int R,int l,int r,int pos)//正常讯问
    {
        if(L<=l&&r<=R)
            return sum[pos];
        down(pos,r-l+1);
        int ans=0;
        int m=(l+r)>>1;
        if(L<=m)ans+=query(L,R,lson);
        if(R>m)ans+=query(L,R,rson);
        return ans;
    }
    
    int main()
    {
        int n,m;
        RII(n,m);
        rep(i,1,m)
        {
            int a,b,c;RIII(a,b,c);
            if(a)
                cout<<query(b,c,1,n,1)<<endl;
            else update(b,c,1,n,1);
        }
        return 0;
    }
    View Code
    
    
  • 相关阅读:
    优化总结文章链接
    帧同步、状态同步
    ecs
    AStarPathFinding
    unity 热更方案对比
    C#数据类型
    JavaScript基础
    CSS中margin和padding的区别
    css选择器
    hadoop中使用shell判断HDFS文件是否存在
  • 原文地址:https://www.cnblogs.com/bxd123/p/10841336.html
Copyright © 2020-2023  润新知