GalaxyOJ-858 (tag线段树)

来源:互联网 发布:织梦cms 地区分站 编辑:程序博客网 时间:2024/05/18 18:01

题目

Problem 858: 区间黑白和
Time Limit: 1000 ms Memory Limit: 131072 KB

Problem Description

给出一个序列a[1..n]。对于任意位置i有两种颜色,黑色与白色(不妨以1指黑,0指白)。

请你维护两个操作。

1.求出连续区间所有某种颜色的位置的a[]和

2.翻转某连续区间所有位置的颜色(黑变白,白变黑)

Input

第一行1个整数n。
第二行n个整数描述a[]。
第三行n个整数描述每个位置的颜色。
接下来一行一个整数m指操作数。
接下来m行,每行对应一个操作,先输入type,
若type=1 ,接下来输入L,R,col(col为0或1)。求出L,R之间的所有颜色为col的a[]和(包括L,R)。
若type=2,接下来输入L,R,翻转L,R之间所有位置的颜色。

对于30%数据满足0<n,m<=1000
对于另外10%数据满足type≠2
对于100%数据满足0<n,m<=100000

Output

按顺序每行回应一个type=1操作,即每行一个整数回答询问的答案。

Sample Input

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

Sample Output

4
5

分析

  • 就是一个裸的线段树吧,tag记录一下它代表的区间是否被翻转颜色。(一遍过了,简单的线段树还算熟练啦~)

程序

#include <cstdio>#include <iostream>#define N 100005using namespace std;int n,m,k,a[N],b[N];struct segment_tree{    //tag 表示其子树(除当前节点)被翻转了     #define X (t[x])    #define Lx (x<<1)    #define Rx ((x<<1)+1)    #define Mid ((l+r)>>1)    #define L (t[Lx])    #define R (t[Rx])    struct node{int v[2],tag,l,r;} t[3*N];    int A,B,C;    void merge(int x){        X.v[0]=L.v[0]+R.v[0];        X.v[1]=L.v[1]+R.v[1];    }    void add_tag(int x){swap(X.v[0],X.v[1]); X.tag^=1;}    void down_tag(int x){        if (X.tag){            add_tag(Lx);            add_tag(Rx);            X.tag=0;        }    }    void change(int x){        if (A<=X.l && X.r<=B){add_tag(x); return;}        down_tag(x);        if (A<=L.r) change(Lx);        if (B>=R.l) change(Rx);        merge(x);    }    int query(int x){        if (A<=X.l && X.r<=B){return X.v[C];};        down_tag(x);        int ret=0;        if (A<=L.r) ret+=query(Lx);        if (B>=R.l) ret+=query(Rx);        return ret;    }    void build(int x,int l,int r){        X.l=l,X.r=r;        if (l==r){X.v[b[l]]+=a[l]; return;}        build(Lx,l,Mid);        build(Rx,Mid+1,r);        merge(x);    }} T;int main(){    freopen("1.txt","r",stdin);    scanf("%d",&n);    for (int i=1; i<=n; i++) scanf("%d",&a[i]);    for (int i=1; i<=n; i++) scanf("%d",&b[i]);    T.build(1,1,n);    for (scanf("%d",&m); m--;){        scanf("%d",&k);        if (k==1){            scanf("%d%d%d",&T.A,&T.B,&T.C);            printf("%d\n",T.query(1));            continue;        }        scanf("%d%d",&T.A,&T.B);        T.change(1);    }}