zoukankan      html  css  js  c++  java
  • 线段树

     [线段树]Easy问题(重庆2006省选)

    Description

    有一个n个元素的数组,每个元素初始均为0。有m条指令,要么让其中一段连续序列数字反转--0变1,1变0(操作1),要么询问某个元素的值(操作2)。 例如当n=20时,10条指令如下:

    操作  回答     操作后的数组

    1 1 10 N/A   11111111110000000000

    2 6   1    11111111110000000000

    2 12  0     11111111110000000000

    1 5 12 N/A   11110000001100000000

    2 6   0    11110000001100000000

    2 15  0     11110000001100000000

    1 6 16 N/A   11110111110011110000

    1 11 17 N/A   11110111111100001000

    2 12   1    11110111111100001000

    2 6   1       11110111111100001000

    Input

    输入第一行包含两个整数n,m,表示数组的长度和指令的条数。以下m行,每行的第一个数t表示操作的种类。若t=1,则接下来有两个数L,R(L<=R),表示区间[L,R]的每个数均反转;若t=2,则接下来只有一个数I,表示询问的下标。

    Output

    输出中有多行.每个操作2输出一行(非0即1),表示每个操作2的回答。

    Sample Input

    20 10
    1 1 10
    2 6
    2 12
    1 5 12
    2 6
    2 15
    1 6 16
    1 11 17
    2 12
    2 6
    

    Sample Output

    1
    0
    0
    0
    1
    1
    

    HINT

    50%的数据满足:1<=n<=1000, 1<=m<=10000。 100%的数据满足:1<=n<=100000, 1<=m<=500000。

    =========================以上题目========================

    #include <cstdio>
    // 4 5|6 7
    // 1 2 3 4 5|6 7 8 9 10
    // 1 2 3 4 5|6 7 8 9
    // 3 4 5 6|7 8 9
    // 3 4 5 6|7 8 9 10
    // 1|2
    int n,m,l[1000001],r[1000001],t[1000001],res = 0;
    //t[i]表示编号为i的线段有几次取反操作。 
    void su(int x,int ll,int rr){
        t[x] = 0;l[x] = ll;r[x] = rr;
        if(ll == rr){return;}
        int len = (rr - ll) / 2;
        su(x * 2,ll,ll + len);
        su(x * 2 + 1,ll + len + 1,rr);
    }
    void f(int x,int a,int b){
        if(l[x] == a && r[x] == b){
            t[x]++;
            return;
        }
        int mid = (l[x] + r[x]) / 2;
        if(a > mid){
            f(x * 2 + 1,a,b);
        }
        else if(b <= mid){
            f(x * 2,a,b);
        }    
        else{
            f(x * 2,a,mid);
            f(x * 2 + 1,mid + 1,b);
        }
    }
    void ask(int x,int a){
        res += t[x];
        if(l[x] == r[x])
            return;
        int mid = (l[x] + r[x]) / 2;
        if(a <= mid){
            ask(x * 2,a);
        }
        else{
            ask(x * 2 + 1,a);
        }
    }
    int main()
    {
        scanf("%d %d",&n,&m);
        su(1,1,n);
        for(int i = 1;i <= m;i++){
            int x,a,b;
            scanf("%d",&x);
            if(x == 1){
                scanf("%d %d",&a,&b);
                f(1,a,b);
            }
            else{
                scanf("%d",&a);
                res = 0;
                ask(1,a);
                printf("%d\n",res % 2);
            }
        }
        return 0;
    } 
  • 相关阅读:
    栈实现队列
    朋友圈的数量
    岛屿的数量
    岛屿的最大面积
    单词最短路径
    矩阵中查找单词
    拨号问题
    CDN原理
    TCP建立连接的三次握手过程
    JavaScript手写几种常见的排序算法:冒泡、选择、插入、希尔、归并、快排
  • 原文地址:https://www.cnblogs.com/frankying/p/6636528.html
Copyright © 2011-2022 走看看