• 线段树


     [线段树]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;
    } 
  • 相关阅读:
    前端代码美化的艺术
    CSS3 简单的砸金蛋样式
    为什么 VS Code 能迅速占领 JavaScript 开发者社区
    了解并使用 CSS 中的 rem 单位
    CSS中一些利用伪类、伪元素和相邻元素选择器的技巧
    SVG入门指南
    PAT 1035 Password [字符串][简单]
    生信学习-二代测序知乎专栏总结[转]
    PAT 1119 Pre- and Post-order Traversals [二叉树遍历][难]
    生信笔记-mooc【武大】
  • 原文地址:https://www.cnblogs.com/frankying/p/6636528.html
Copyright © 2020-2023  润新知