序列操作
operation
【题目描述】
lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:
0 a b 把[a, b]区间内的所有数全变成0
1 a b 把[a, b]区间内的所有数全变成1
2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0
3 a b 询问[a, b]区间内总共有多少个1
4 a b 询问[a, b]区间内最多有多少个连续的1
对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?
【输入】
输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目
第二行包括n个数,表示序列的初始状态
接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b<n)表示对于区间[a, b]执行标号为op的操作
【输出】
对于每一个询问操作,输出一行,包括1个数,表示其对应的答案
【样例输入】
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
【样例输出】
5
2
6
5
【数据范围】
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
SC2010省选题目。
很BT的一道题,做了我一个下午加上一个晚上,总共275行,吓哭了。
神奇的是,今天晚上一晚上都没有调,仅仅是静态查错了两个小时就AC了,貌似效率是很高的,希望做出了这道题之后就能入门线段树了。
今天我听取了很多人的意见。一是OJ说的,要一个功能一个功能地添加。二是王哥说的很重要的静态差错。
这道题和Rqnoj626那道小白逛公园基本上是一样的思路,当找连续最长的时候,分三种情况:在左边找连续最长,在右边找连续最长,在中间找连续最长。
但是由于这道题特殊性,维护maxl和maxr的时候,不能够像626那样做。因为不能够直接取左儿子或右儿子的sum,因为0此时没有被取到。
(可以证明,最后维护出来的maxn总是包含了maxl和maxr这两种情况)
——————————————————————————————————————————————————————————————————————————
先分模块来讲:
build()是很标准的,和626一模一样。
0和1对应的模块比较标准,不过对于我这个新手,还是花了很长时间来理解,检查。
首先如果当前区间值等于要填充的值,就直接返回。
如果要填充的区间包含了当前区间,则填充。
接下来,同626,很重要的一个部分,如果当前节点有懒标记(我听WG的,就用同填充线段那种方式,用-1表示杂色或者说懒标记(没有用LX用的那个布尔懒标记)),则将当前节点的信息向下传递。(这个步骤虽然让线段树有点退化,但是不会完全退化,也是效率高的重要原因)
然后就是标准的分情况讨论。(如CY说的那样,线段树都分成4种情况),之后更新(只要是涉及到修改的,建树、翻转、设置,都要有更新)。
向下传递在除了build之外所有的模块中都用到了,而且一模一样。(注意:查询模块也必须有向下传递,很容易理解但是容易忽略)
容易打错的地方是:如果当前节点状态为1,则左子节点的sum值=m-l+1,右节点sum值=r-m。
翻转模块与更改模块几乎一模一样。只有边界稍有不同。flip的边界是找到一块纯色区域且在被待修改区间包含的一个区间,然后将状态取反,就一模一样了。
我写冗杂了,其实count,和longgest功能是完全一样的,但是我分开写了。只不过也许这样反而让程序效率变高了,因为几乎每个点都比其他同学快。
很简单,与626一模一样,注意好懒标记向下传就好。
updata与626一模一样。
——————————————————————————————————————————————————————————————————————————
总结一些回忆得起来的经验
1、做的时候,要注意函数体内的return,有的重要的函数常常放在了最后,而很早就return了,没有执行这些重要的函数。比如说有时候的后序遍历的updata。
2、要训练自己的全局意识,比如说今天打了很多重复的代码,最后才发现是一模一样的,那个updata和那个向下传递就是例子,调试了很久才发现实现是一模一样的才把他们放入一个单独模块里,耽搁时间了。一开始应该仔细考虑这些程序内在的联系才好。
还有longgest和count其实也是一模一样的。
3。。。
#include <cstdio>
struct node
{
long sta;
long s1;
long maxl;
long maxr;
long maxn;
};
node tree[400002];
long n;long m;
bool que[100002];
void updata(node& ans,node& u,node& v)
{
if (u.sta == 1)
ans.maxl = u.s1 + v.maxl;
else ans.maxl = u.maxl;
if (v.sta == 1)
ans.maxr = v.s1 + u.maxr;
else ans.maxr = v.maxr;
if (u.maxn > v.maxn)
ans.maxn = u .maxn;
else ans.maxn = v.maxn;
if (ans.maxn < u.maxr+v.maxl)
ans.maxn = u.maxr+v.maxl;
if (u.sta == v.sta)
ans.sta = u.sta;
else ans.sta = -1;
ans.s1 = u.s1+v.s1;
}
void set(long l,long r,long p,long a,long b,long c)
{
long m = (l+r)>>1;
if (tree[p].sta == c)
{
return;
}
if (a <= l && b >= r)
{
tree[p].sta = c;
if (c == 1)
{
tree[p].s1 = r-l+1;
tree[p].maxl = tree[p].maxr = tree[p].maxn = r-l+1;
}
else
{
tree[p].s1 = 0;
tree[p].maxl = tree[p].maxr = tree[p].maxn = 0;
}
return;
}
if (tree[p].sta > -1)
{
tree[p<<1].sta = tree[(p<<1)+1].sta = tree[p].sta;
if (tree[p].sta == 0)
{
tree[p<<1].s1 = tree[(p<<1)+1].s1 = 0;
tree[p<<1].maxl = tree[p<<1].maxr = tree[p<<1].maxn = 0;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxr = tree[(p<<1)+1].maxn = 0;
}
else
{
tree[p<<1].s1 = m-l+1;
tree[(p<<1)+1].s1 = r-m;
tree[p<<1].maxl = tree[p<<1].maxr = tree[p<<1].maxn = m-l+1;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxr = tree[(p<<1)+1].maxn = r-m;
}
}
if (b <= m)
{
set(l,m,p<<1,a,b,c);
}
else if (a > m)
{
set(m+1,r,(p<<1)+1,a,b,c);
}
else
{
set(l,m,p<<1,a,b,c);
set(m+1,r,(p<<1)+1,a,b,c);
}
updata(tree[p],tree[p<<1],tree[(p<<1)+1]);
}
void build(long l,long r,long p)
{
long m = (l+r)>>1;
if (l == r)
{
tree[p].sta = que[l];
if (que[l] == 1)
tree[p].maxl = tree[p].maxr = tree[p].maxn = tree[p].s1 = 1;
else
tree[p].maxl = tree[p].maxr = tree[p].maxn = tree[p].s1 = 0;
return;
}
build(l,m,p<<1);
build(m+1,r,(p<<1)+1);
updata(tree[p],tree[p<<1],tree[(p<<1)+1]);
}
long count(long l,long r,long p,long a,long b)
{
long m = (l+r)>>1;
if (a <= l && b>= r)
{
return tree[p].s1;
}
if (tree[p].sta > -1)
{
tree[p<<1].sta = tree[(p<<1)+1].sta = tree[p].sta;
if (tree[p].sta == 0)
{
tree[p<<1].s1 = tree[(p<<1)+1].s1 = 0;
tree[p<<1].maxl = tree[p<<1].maxr = tree[p<<1].maxn = 0;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxr = tree[(p<<1)+1].maxn = 0;
}
else
{
tree[p<<1].s1 = m-l+1;
tree[(p<<1)+1].s1 = r-m;
tree[p<<1].maxl = tree[p<<1].maxr = tree[p<<1].maxn = m-l+1;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxr = tree[(p<<1)+1].maxn = r-m;
}
}
if (b <= m)
{
return count(l,m,p<<1,a,b);
}
if (a > m)
{
return count(m+1,r,(p<<1)+1,a,b);
}
{
long u = count(l,m,p<<1,a,b);
long v = count(m+1,r,(p<<1)+1,a,b);
return u+v;
}
}
void flip(long l,long r,long p,long a,long b)
{
long m = (l+r)>>1;
if (a<=l&&b>=r&&tree[p].sta > -1)
{
tree[p].sta = (tree[p].sta+1)&1;
if (tree[p].sta == 0)
{
tree[p].s1 = 0;
tree[p].maxl = tree[p].maxr = tree[p].maxn = 0;
}
else
{
tree[p].s1 = r-l+1;
tree[p].maxl = tree[p].maxr = tree[p].maxn = r-l+1;
}
return;
}
if (tree[p].sta > -1)
{
tree[p<<1].sta = tree[(p<<1)+1].sta = tree[p].sta;
if (tree[p].sta == 0)
{
tree[p<<1].s1 = tree[(p<<1)+1].s1 = 0;
tree[p<<1].maxl = tree[p<<1].maxn = tree[p<<1].maxr = 0;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxn = tree[(p<<1)+1].maxr = 0;
}
else
{
tree[p<<1].s1 = m-l+1;
tree[(p<<1)+1].s1 = r-m;
tree[p<<1].maxl = tree[p<<1].maxn = tree[p<<1].maxr = m-l+1;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxn = tree[(p<<1)+1].maxr = r-m;
}
}
if (b <= m)
{
flip(l,m,p<<1,a,b);
}
else if (a > m)
{
flip(m+1,r,(p<<1)+1,a,b);
}
else
{
flip(l,m,p<<1,a,b);
flip(m+1,r,(p<<1)+1,a,b);
}
updata(tree[p],tree[p<<1],tree[(p<<1)+1]);
}
node longgest(long l,long r,long p,long a,long b)
{
long m = (l+r)>>1;
if (a <= l && b >= r)
return tree[p];
if (tree[p].sta > -1)
{
tree[p<<1].sta = tree[(p<<1)+1].sta = tree[p].sta;
if (tree[p].sta == 0)
{
tree[p<<1].s1 = tree[(p<<1)+1].s1 = 0;
tree[p<<1].maxl = tree[p<<1].maxn = tree[p<<1].maxr = 0;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxn = tree[(p<<1)+1].maxr = 0;
}
else
{
tree[p<<1].s1 = m-l+1;
tree[(p<<1)+1].s1 = r-m;
tree[p<<1].maxl = tree[p<<1].maxn = tree[p<<1].maxr = m-l+1;
tree[(p<<1)+1].maxl = tree[(p<<1)+1].maxn = tree[(p<<1)+1].maxr = r-m;
}
}
if (a > m)
{
return longgest(m+1,r,(p<<1)+1,a,b);
}
if (b <= m)
{
return longgest(l,m,p<<1,a,b);
}
node u = longgest(l,m,p<<1,a,b);
node v = longgest(m+1,r,(p<<1)+1,a,b);
node ans;
updata(ans,u,v);
return ans;
}
int main()
{
freopen("operation.in","r",stdin);
freopen("operation.out","w",stdout);
scanf("%ld%ld",&n,&m);
for (long i=1;i<n+1;i++)
scanf("%ld",que+i);
build(1,n,1);
for (long i=1;i<m+1;i++)
{
long op;long a;long b;
scanf("%ld%ld%ld",&op,&a,&b);
a++;b++;
switch(op)
{
case 0:
set(1,n,1,a,b,0);
break;
case 1:
set(1,n,1,a,b,1);
break;
case 2:
flip(1,n,1,a,b);
break;
case 3:
printf("%ld\n",count(1,n,1,a,b));
break;
case 4:
printf("%ld\n",longgest(1,n,1,a,b).maxn);
break;
}
}
return 0;
}