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

    NOI2009 开关

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

    两种操作分别是区间更改(取反)和区间查询。这道题无疑是用线段树做。

    需要特别去想的是,延迟标记向下传递的时候,当前节点的懒标记若存在,则表示区间需要取反,更新的sum是用区间总数减去之前的灯数。

     1 #include<iostream>
     2 using namespace std;
     3 const int SIZE = 100005;
     4 struct SegmentTree{
     5     int l, r, sum;
     6     bool p;
     7 }t[SIZE * 4];
     8 void build(int p, int l, int r){
     9     t[p].l = l, t[p].r = r;
    10     if(l == r) return;
    11     int mid = (l + r) >> 1;
    12     build(p*2, l, mid);
    13     build(p*2+1, mid+1, r);
    14 }
    15 
    16 void spread(int p){
    17     if(t[p].p){
    18         t[p*2].sum = t[p*2].r-t[p*2].l+1 - t[p*2].sum;
    19         t[p*2+1].sum = t[p*2+1].r-t[p*2+1].l+1 - t[p*2+1].sum;
    20         t[p*2].p = !t[p*2].p;
    21         t[p*2+1].p = !t[p*2+1].p;
    22         t[p].p = 0;
    23     }
    24 }
    25 void change(int p, int l, int r){
    26     if(l <= t[p].l && r >= t[p].r) {
    27         t[p].p = !t[p].p;
    28         t[p].sum = t[p].r-t[p].l+1 - t[p].sum;
    29         return;
    30     }    
    31     spread(p);
    32     int mid = (t[p].l + t[p].r) >> 1;
    33     if (l <= mid) change(p*2, l, r);
    34     if(r > mid) change(p*2+1, l, r);
    35     t[p].sum = t[p*2].sum + t[p*2+1].sum;
    36 }
    37 
    38 int ask(int p, int l, int r){
    39     if(l <= t[p].l && r >= t[p].r){
    40         return t[p].sum;
    41     }
    42     spread(p);
    43     int mid = (t[p].l + t[p].r) >> 1;
    44     int val = 0;
    45     if(l <= mid) val += ask(p*2, l, r);
    46     if(r > mid) val += ask(p*2+1, l, r);
    47     return val;
    48 }
    49 
    50 int main(){
    51     int n, m;
    52     cin >> n >> m;
    53     build(1, 1, n);
    54     while(m--){
    55         int f, x, y;
    56         cin >> f >> x >> y;
    57         switch(f){
    58             case 0:
    59                 change(1, x, y);
    60                 break;
    61             case 1:
    62                 cout << ask(1, x, y) <<"
    ";
    63                 break;
    64         }
    65     }
    66     
    67     
    68     
    69     return 0;
    70 }
  • 相关阅读:
    基于openpose的动作识别(一)检测人脸人手
    12.4第三天
    安装linux windows双系统
    python学习之argparse模块
    win10安装linux虚拟机
    使用labelImg训练模型并用yolo3进行识别的工作流程
    使用labelImg标注数据的方法
    VirtualBox网络连接方式
    HttpWebRequest 请求带OAuth2 授权的webapi
    Bootstrap table 分页 In asp.net MVC
  • 原文地址:https://www.cnblogs.com/hnoi/p/11188161.html
Copyright © 2011-2022 走看看