线段树1(带懒惰标记的区间更新和整棵树的查询)

来源:互联网 发布:c语言经典算法100例 编辑:程序博客网 时间:2024/04/28 17:08

 Problem Description

皮特的幸运数是2和5。只由幸运数字2和5组成的数列,称为幸运数列。对于幸运数列,有两种操作。

1、switch i j

表示数列从第i个数到第j个数中,所有的2改成5,所有的5改成2.例如幸运数列25525,执行switch 2 4操作,则数列变成22255

2、count

表示要求输出当前幸运数列的最长不下降子序列(即子序列中后面的数都不小于前面的数)的长度。例如幸运数列252255,其中222,555,2555是它的不下降子序列,而2525不是,可以看出,最长不下降子序列是22255,长度为5。

现在给出一个长度为n的幸运数列,再依次给出m个操作,对于每个count操作,输出当前幸运数列的最长不下降子序列的长度。

 Input

输入包含多组数据。(数据不超过10组)

每组数据的第一行有两个整数n,m(n,m<=100000),分别表示数列的长度和操作个数。

接下来一行,有一个长度为n的只由2和5构成的数列。

接下来m行,每行一个操作,是count或者switch i j,含义如题所述

 Output

对于每组数据的每个count操作,都输出一行,包含一个整数,表示当前幸运数列的最长不下降子序列的长度。



#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int MAXN=100005;struct TREE{int l2,l5,l25,l52;bool flag;}tree[501000];char num[101000];void PushUp(int node){tree[node].l2=tree[node<<1].l2+tree[node<<1|1].l2;tree[node].l5=tree[node<<1].l5+tree[node<<1|1].l5;tree[node].l25=max(tree[node<<1].l25+tree[node<<1|1].l5,tree[node<<1].l2+tree[node<<1|1].l25);tree[node].l52=max(tree[node<<1].l52+tree[node<<1|1].l2,tree[node<<1].l5+tree[node<<1|1].l52);}void Build(int node ,int left,int right){tree[node].flag=false;if(left==right){if(num[left]=='2'){tree[node].l2=1;tree[node].l5=0;tree[node].l25=1;tree[node].l52=1;}else if(num[left]=='5'){tree[node].l2=0;tree[node].l5=1;tree[node].l25=1;tree[node].l52=1;}}else{int mid=(left+right)>>1;Build(node<<1,left,mid);Build(node<<1|1,mid+1,right);PushUp(node);}}void change(int node,int l,int r,int ql,int qr){if(l==r)//一个点,直接改{swap(tree[node].l2,tree[node].l5);swap(tree[node].l25,tree[node].l52);}else if(l==ql&&r==qr)//正好对应线段树上的区间,打懒惰标记,先不修改子树{swap(tree[node].l2,tree[node].l5);swap(tree[node].l25,tree[node].l52);tree[node].flag^=1;}else//在线段树的不同区间内{int mid=l+r>>1;if(tree[node].flag)//解决懒惰标记,向下修改,分两段{change(node<<1,l,mid,l,mid);change(node<<1|1,mid+1,r,mid+1,r);tree[node].flag=false;}if(qr<=mid)change(node<<1,l,mid,ql,qr);//全在左边else if(ql>mid)change(node<<1|1,mid+1,r,ql,qr);//全在右边else//左右都有{change(node<<1,l,mid,ql,mid);change(node<<1|1,mid+1,r,mid+1,qr);}PushUp(node);}}int query(int node,int l,int r){return max(tree[node].l25,max(tree[node].l2,tree[node].l5));}int main(){int n,m,i,l,r;char ope[10];while(scanf("%d %d",&n,&m)!=EOF){memset(tree,0,sizeof(tree));scanf("%s",num+1);//printf("%s",num+1);Build(1,1,n);for(i=0;i<m;i++){scanf("%s",ope);if(ope[0]=='s'){scanf("%d %d",&l,&r);change(1,1,n,l,r);}else if(ope[0]=='c'){printf("%d\n",query(1,1,n));}}}return 0;}


0 0
原创粉丝点击