线段树

 [线段树]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;
} 
原文地址:https://www.cnblogs.com/frankying/p/6636528.html