题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858

线段树...调了一个上午...(后面带 // 的都是改出来的)

lazy 标记的下放好麻烦,还得考虑赋值和取反的先后顺序什么的...

因为在取反时把赋值标记 swap 了,所以下放的时候先判断取反再判断赋值...

而且WA了一上午的原因竟然是一开始不慎把取反以为成翻转了,后来没改干净...那个 rev 的名字啊...

总之没有太改变自己最初的想法、改了些细节就A了还是很高兴的!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=1e5+;
int n,m,op,a,b,c[maxn];
struct N{
int sum,z[],y[],m[];
int lz[],rev,len;
}t[maxn<<];
int rd()
{
int ret=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret;
}
void pushup(int x)
{
int ls=(x<<),rs=(x<<|);
t[x].sum=t[ls].sum+t[rs].sum;
for(int i=;i<=;i++)
{
t[x].z[i]=t[ls].z[i]+(t[ls].z[i]==t[ls].len?t[rs].z[i]:);
t[x].y[i]=t[rs].y[i]+(t[rs].y[i]==t[rs].len?t[ls].y[i]:);
// t[x].m[i]=max(max(t[x].z[i],t[x].y[i]),t[ls].y[i]+t[rs].z[i]);//
t[x].m[i]=max(max(t[ls].m[i],t[rs].m[i]),t[ls].y[i]+t[rs].z[i]);//
}
}
void upt(int x,int val)//赋值
{
t[x].lz[val]=;
t[x].lz[!val]=; t[x].rev=;//!
t[x].sum=t[x].len*val;
t[x].z[val]=t[x].y[val]=t[x].m[val]=t[x].len;
t[x].z[!val]=t[x].y[!val]=t[x].m[!val]=;
}
void re(int x)//取反
{
swap(t[x].z[],t[x].z[]); swap(t[x].y[],t[x].y[]);//!!!
swap(t[x].m[],t[x].m[]);
t[x].sum=t[x].len-t[x].sum; t[x].rev^=;
swap(t[x].lz[],t[x].lz[]);//!
}
void pushdown(int x)
{
// if(t[x].len==1)return;//
int ls=(x<<),rs=(x<<|);
if(t[x].rev)t[x].rev^=,re(ls),re(rs);
for(int v=;v<=;v++)
if(t[x].lz[v])t[x].lz[v]=,upt(ls,v),upt(rs,v);//顺序
}
void build(int x,int l,int r)
{
t[x].len=r-l+;
if(l==r)
{
t[x].z[c[l]]=t[x].y[c[l]]=t[x].m[c[l]]=;
t[x].sum=c[l]; //
return;
}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
void update(int x,int l,int r,int L,int R,int val)
{
if(l>=L&&r<=R)
{
upt(x,val);return;
}
pushdown(x);
int mid=((l+r)>>);
if(mid>=L)update(x<<,l,mid,L,R,val);
if(mid<R)update(x<<|,mid+,r,L,R,val);
pushup(x);
}
void rever(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
re(x);return;
}
int mid=((l+r)>>);
pushdown(x);
if(mid>=L)rever(x<<,l,mid,L,R);
if(mid<R)rever(x<<|,mid+,r,L,R);
pushup(x);
}
int query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x].sum;
int mid=((l+r)>>),ret=;
pushdown(x);
if(mid>=L)ret+=query(x<<,l,mid,L,R);
if(mid<R)ret+=query(x<<|,mid+,r,L,R);
return ret;
}
int ask(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x].m[];
pushdown(x);//
int mid=((l+r)>>);
if(mid>=R)return ask(x<<,l,mid,L,R);
if(mid<L)return ask(x<<|,mid+,r,L,R);
int ret=;
ret=max(ask(x<<,l,mid,L,R),ask(x<<|,mid+,r,L,R));
ret=max(ret,min(t[x<<].y[],mid-L+)+min(t[x<<|].z[],R-mid));
return ret;
}
int main()
{
n=rd();m=rd();
for(int i=;i<=n;i++)c[i]=rd();
build(,,n);
while(m--)
{
op=rd(); a=rd()+; b=rd()+;
if(op==||op==)update(,,n,a,b,op);
if(op==)rever(,,n,a,b);
if(op==)printf("%d\n",query(,,n,a,b));
if(op==)printf("%d\n",ask(,,n,a,b));
}
return ;
}

bzoj1858 [Scoi2010]序列操作——线段树的更多相关文章

  1. bzoj1858[Scoi2010]序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 3079  Solved: 1475[Submit][Statu ...

  2. 【BZOJ-1858】序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1961  Solved: 991[Submit][Status ...

  3. BZOJ 1858: [Scoi2010]序列操作( 线段树 )

    略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...

  4. 【bzoj1858】[Scoi2010]序列操作 线段树区间合并

    题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...

  5. Luogu P2572 [SCOI2010]序列操作 线段树。。

    咕咕了...于是借鉴了小粉兔的做法ORZ... 其实就是维护最大子段和的线段树,但上面又多了一些操作....QWQ 维护8个信息:1/0的个数(sum),左/右边起1/0的最长长度(ls,rs),整段 ...

  6. 洛谷$P2572\ [SCOI2010]$ 序列操作 线段树/珂朵莉树

    正解:线段树/珂朵莉树 解题报告: 传送门$w$ 本来是想写线段树的,,,然后神仙$tt$跟我港可以用珂朵莉所以决定顺便学下珂朵莉趴$QwQ$ 还是先写线段树做法$QwQ$? 操作一二三四都很$eas ...

  7. [SCOI2010]序列操作 线段树

    ---题面--- 题解: 在考场上打的这道题,出人意料的很快就打完了?! 直接用线段树,维护几个东西: 1,lazy标记 : 表示区间赋值 2,mark标记:表示区间翻转 3,l1:前缀最长连续的1的 ...

  8. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  9. BZOJ1858 [Scoi2010]序列操作(线段树)

    题目链接 [Scoi2010]序列操作 考验代码能力的一道好题. 思想还是很简单的(直接上线段树),但是比较难写. #include <bits/stdc++.h> using names ...

随机推荐

  1. python 快排,堆排,归并

    #归并排序 def mergeSort(a,L,R) :     if(L>=R) :         return     mid=((L+R)>>1)     mergeSort ...

  2. Uva10294 Arif in Dhaka (置换问题)

    扯回正题,此题需要知道的是置换群的概念,这点在刘汝佳的书中写的比较详细,此处不多做赘述.此处多说一句的是第二种手镯的情况.在下图中“左图顺时针转1个位置”和“右图顺时针旋转5个位置”是相同的,所以在最 ...

  3. Bzoj 2726 SDOI 任务安排

      Memory Limit: 131072KB   64bit IO Format: %lld & %llu Description 机器上有N个需要处理的任务,它们构成了一个序列.这些任务 ...

  4. MySQL的字符串连接函数CONCAT, CONCAT_WS,GROUP_CONTACT

    本文转载自de.cel<MySQL的字符串连接函数CONCAT, CONCAT_WS,GROUP_CONCAT>   在搜索Mysql中怎么实现把一列的多行数据合并成一行时,找到了grou ...

  5. mysql 常用管理命令

    常见的管理mysql命令 (1)用于选择在MySQL工作区指定的数据库(选择数据库): USE Databasename; (2)列出了MySQL数据库管理系统中的所有可访问的数据库: SHOW DA ...

  6. POJ 2346 【DP】

    题意: 给一个正的不大于10的偶数n,求n个数字组成的数字串前n/2位和后n/2位的和相等的个数. 思路: dp[i][j]由i位数组成的和为j的数字串的个数. dp[i][j]+=dp[i-1][j ...

  7. 【python】搜索引擎方面的资料

    http://blog.csdn.net/hguisu/article/category/1230933

  8. POJ 1679 The Unique MST 推断最小生成树是否唯一

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22715   Accepted: 8055 D ...

  9. python爬虫(二)--了解deque

    队列-deque 有了上面一节的基础.当然你须要全然掌握上一节的全部方法,由于上一节的方法.在以下的教程中 会重复的用到. 假设你没有记住,请你返回上一节. http://blog.csdn.net/ ...

  10. hi3531 SDK已编译文件系统制作jffs2文件系统镜像并解决这个问题 .

    一, 安装SDK 1.Hi3531 SDK包位置 在"Hi3531_V100R001***/01.software/board"文件夹下,您能够看到一个 Hi3531_SDK_Vx ...