zoukankan      html  css  js  c++  java
  • Codevs_1690_开关灯_(线段树)

    描述


    http://codevs.cn/problem/1690/

    一排共 n 个灯,起初都是关着的,现在有 m 次操作. 0 开头的操作代表将 l ~ r 的开关按一遍,1 开头的操作代表询问 l ~ r 共多少个开着的灯.

    1690 开关灯

    USACO

    时间限制: 1 s
    空间限制: 128000 KB
    题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

        YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这些路灯全是关着的,六点之后,会有M(2<=m& lt;=100000)个人陆续按下开关,这些开关可以改变从第i盏灯到第j盏灯的状态,现在YYX想知道,从第x盏灯到第y盏灯中有多少是亮着的(1& lt;=i,j,x,y<=N)

    输入描述 Input Description
    第 1 行: 用空格隔开的两个整数N和M
    第 2..M+1 行: 每行表示一个操作, 有三个用空格分开的整数: 指令号(0代表按下开关,1代表询问状态), x 和 y 
    输出描述 Output Description

    第 1..询问总次数 行:对于每一次询问,输出询问的结果

    样例输入 Sample Input

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

    样例输出 Sample Output
    1
    2
     
    数据范围及提示 Data Size & Hint

    一共4盏灯,5个操作,下面是每次操作的状态(X代表关上的,O代表开着的):

    XXXX -> OOXX -> OXOO -> 询问1~3 -> OOXX -> 询问1~4

    分析 


    刚开始想的是用 0 , 1 , -1 分别代表区间都是关着的,都是开着的,有开的又有关的,跟新和查询的时候都是查找到非 -1 的区间再做处理,但是 TLE 了.

    想一下如果灯是 1 0 1 0 1 0 1 0 1...这样排列的,那就退化得不成样子了.

    所以用 on 和 off 分别代表区间内开着的和关着的等的数量,如果按开关,就把这两个值交换.

    最后可以不用 off ,只用一个 on ,可以通过区间长度进行计算.

     1 #include<cstdio>
     2 
     3 const int maxn=100005;
     4 struct node { int l,r; int on;bool d; }a[3*maxn];
     5 int n,m;
     6 
     7 void build_tree(int l,int r,int k)
     8 {
     9     a[k].l=l; a[k].r=r; a[k].on=0; a[k].d=false;
    10     if(l==r) return;
    11     int mid=l+(r-l)/2;
    12     build_tree(l,mid,2*k);
    13     build_tree(mid+1,r,2*k+1);
    14 }
    15 
    16 inline void turn(int k)
    17 {
    18     a[k].on=(a[k].r-a[k].l+1)-a[k].on;
    19     a[k].d^=true;
    20 }
    21 
    22 void update(int l,int r,int k)
    23 {
    24     if(a[k].l==l&&a[k].r==r)
    25     {
    26         turn(k);
    27         return;
    28     }
    29     if(a[k].d)
    30     {
    31         turn(2*k);
    32         turn(2*k+1);
    33         a[k].d=false;
    34     }
    35     int mid=a[k].l+(a[k].r-a[k].l)/2;
    36     if(r<=mid) update(l,r,2*k);
    37     else if(l>mid) update(l,r,2*k+1);
    38     else { update(l,mid,2*k); update(mid+1,r,2*k+1); }
    39     a[k].on=a[2*k].on+a[2*k+1].on;
    40 }
    41 
    42 int search(int l,int r,int k)
    43 {
    44     if(a[k].l==l&&a[k].r==r) return a[k].on;
    45     if(a[k].d)
    46     {
    47         turn(2*k);
    48         turn(2*k+1);
    49         a[k].d=false;
    50     }
    51     int mid=a[k].l+(a[k].r-a[k].l)/2;
    52     if(r<=mid) return search(l,r,2*k);
    53     else if(l>mid) return search(l,r,2*k+1);
    54     else return search(l,mid,2*k)+search(mid+1,r,2*k+1);
    55 }
    56 
    57 int main()
    58 {
    59     scanf("%d%d",&n,&m);
    60     build_tree(1,n,1);
    61     
    62     int qry,l,r;
    63     for(int i=1;i<=m;i++)
    64     {
    65         scanf("%d%d%d",&qry,&l,&r);
    66         switch(qry)
    67         {
    68             case 0:
    69                 update(l,r,1);
    70                 break;
    71             case 1:
    72                 printf("%d
    ",search(l,r,1));
    73                 break;
    74         }
    75     }
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    2016CCPC长春
    POJ 3974
    CH 1401
    POJ 1426
    hihocoder 1829
    江南OJ 1151
    POJ 3279
    POJ 3349
    POJ 3278
    ZOJ 3983
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5435903.html
Copyright © 2011-2022 走看看