zoukankan      html  css  js  c++  java
  • P3870 开关

    题目描述

    现有 nn 盏灯排成一排,从左到右依次编号为:11,22,……,nn。然后依次执行 mm 项操作。

    操作分为两种:

    1. 指定一个区间 [a,b][a,b],然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开);
    2. 指定一个区间 [a,b][a,b],要求你输出这个区间内有多少盏灯是打开的。

    灯在初始时都是关着的。

    输入格式

    第一行有两个整数 nn 和 mm,分别表示灯的数目和操作的数目。

    接下来有 mm 行,每行有三个整数,依次为:cc、aa、bb。其中 cc 表示操作的种类。

    • 当 cc 的值为 00 时,表示是第一种操作。
    • 当 cc 的值为 11 时,表示是第二种操作。

    aa 和 bb 则分别表示了操作区间的左右边界。

    输出格式

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

    输入输出样例

    输入 #1复制

    4 5
    0 1 2
    0 2 4
    1 2 3
    0 2 4
    1 1 4
    

    输出 #1复制

    1
    2
    

    说明/提示

    数据规模与约定

    对于全部的测试点,保证 2le nle 10^52≤n≤105,1le mle 10^51≤m≤105,1le a,ble n1≤a,bn,cin{0,1}c∈{0,1}。

    思路

    线段树区间修改区间求和

    开和关 异或

    lazy标志只需记录更改几次

    根据lazy值奇偶性观察区间和是否需要改变

    代码

    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int MAXN=1e5+50;
    
    struct node
    {
        int l,r;
        int sum,lazy;
        void add(int x)  //**
        {
            if(x%2)
                sum=(r-l+1)-sum;
            lazy+=x;
        }
    }tree[MAXN*4];
    
    int ar[MAXN];
    
    void push_up(int id)
    {
        tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
    }
    
    void push_down(int id)
    {
        tree[id<<1].add(tree[id].lazy);
        tree[id<<1|1].add(tree[id].lazy);
        tree[id].lazy=0;
    }
    
    void buildTree(int id,int l,int r)
    {
        tree[id].l=l;
        tree[id].r=r;
        tree[id].sum=tree[id].lazy=0;
        if(l==r)
            tree[id].sum=ar[l];
        else
        {
            int mid=(l+r)>>1;
            buildTree(id<<1,l,mid);
            buildTree(id<<1|1,mid+1,r);
            push_up(id);
        }
    }
    
    void update(int id,int l,int r,int val)
    {
        int L=tree[id].l,R=tree[id].r;
        if(l<=L&&R<=r)
            tree[id].add(val);
        else
        {
            push_down(id);
            int mid=(L+R)>>1;
            if(mid>=l)
                update(id<<1,l,r,val);
            if(mid<r)
                update(id<<1|1,l,r,val);
            push_up(id);
        }
    }
    
    ll query(int id,int l,int r)
    {
        int L=tree[id].l,R=tree[id].r;
        if(l<=L&&R<=r)
            return tree[id].sum;
        push_down(id);
        int mid=(L+R)>>1;
        ll res=0;
        if(mid>=l)
            res+=query(id<<1,l,r);
        if(mid<r)
            res+=query(id<<1|1,l,r);
        push_up(id);
        return res;
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        int i,n,q,a,b,d;
        int opr;
        cin>>n>>q;
        //for(i=1;i<=n;i++)
         //   cin>>ar[i];
        buildTree(1,1,n);
        while(q--)
        {
            cin>>opr;
            if(opr==1)
            {
                cin>>a>>b;
                cout<<query(1,a,b)<<'
    ';
            }
            else
            {
                cin>>a>>b;
                update(1,a,b,1);
            }
        }
    
        return 0;
    }
    
    
    线段树板子
    /*C a b c 将[a,b]之间的值增加c
    Q a b 查询[a,b]之和*/  
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int MAXN=1e5+50;
    
    struct node
    {
        int l,r;
        ll sum,lazy;
        void add(ll x)
        {
            sum+=x*(r-l+1);
            lazy+=x;
        }
    }tree[MAXN*4];
    
    int ar[MAXN];
    
    void push_up(int id)
    {
        tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
    }
    
    void push_down(int id)
    {
        tree[id<<1].add(tree[id].lazy);
        tree[id<<1|1].add(tree[id].lazy);
        tree[id].lazy=0;
    }
    
    void buildTree(int id,int l,int r)
    {
        tree[id].l=l;
        tree[id].r=r;
        tree[id].sum=tree[id].lazy=0;
        if(l==r)
            tree[id].sum=ar[l];
        else
        {
            int mid=(l+r)>>1;
            buildTree(id<<1,l,mid);
            buildTree(id<<1|1,mid+1,r);
            push_up(id);
        }
    }
    
    void update(int id,int l,int r,ll val)
    {
        int L=tree[id].l,R=tree[id].r;
        if(l<=L&&R<=r)
            tree[id].add(val);
        else
        {
            push_down(id);
            int mid=(L+R)>>1;
            if(mid>=l)
                update(id<<1,l,r,val);
            if(mid<r)
                update(id<<1|1,l,r,val);
            push_up(id);
        }
    }
    
    ll query(int id,int l,int r)
    {
        int L=tree[id].l,R=tree[id].r;
        if(l<=L&&R<=r)
            return tree[id].sum;
        push_down(id);
        int mid=(L+R)>>1;
        ll res=0;
        if(mid>=l)
            res+=query(id<<1,l,r);
        if(mid<r)
            res+=query(id<<1|1,l,r);
        push_up(id);
        return res;
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        int i,n,q,a,b,d;
        char opr[5];
        cin>>n>>q;
        for(i=1;i<=n;i++)
            cin>>ar[i];
        buildTree(1,1,n);
        while(q--)
        {
            cin>>opr;
            if(opr[0]=='Q')
            {
                cin>>a>>b;
                cout<<query(1,a,b)<<'
    ';
            }
            else
            {
                cin>>a>>b>>d;
                update(1,a,b,d);
            }
        }
        
        return 0;
    }
    
  • 相关阅读:
    Spring集成XFire开发WebService
    【ASP.NET】验证控件
    中文分词——正向最大匹配法
    fastdfs storage server的设计与实现
    php浮点数精确运算
    完整导出IntelliJ IDEA的快捷键
    时空理论-结构-空间,运动-时间
    结构论-系统的结构逻辑
    结构主义理论-时空一体才是存在的本源
    分形几何学
  • 原文地址:https://www.cnblogs.com/xxffxx/p/13953448.html
Copyright © 2011-2022 走看看