【BZOJ-1858】序列操作 线段树
1858: [Scoi2010]序列操作
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1961 Solved: 991
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
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
Sample Output
2
6
5
HINT
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
Source
Solution
线段树裸题,但是...
维护各种量:左/右端点,区间大小,覆盖标记,翻转标记,1/0的数量,连续出现次数,左右段的量,是否完全覆盖....
标记之间各种相互作用...比如 覆盖标记时清零翻转标记...
向上更新值的时候,不太同于以往..分类讨论左右段来合并..
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100010
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int n,m;
struct Treenode{int tag,rev,l,r,size,sum[],L[],R[],num[],da;}tree[maxn<<];
inline Treenode merge(Treenode a,Treenode b)
{
Treenode re;
re.l=a.l; re.r=b.r; re.size=re.r-re.l+; re.rev=; re.tag=-;
re.L[]=a.L[]; re.L[]=a.L[]; re.R[]=b.R[]; re.R[]=b.R[];
re.num[]=max(a.num[],b.num[]); re.num[]=max(a.num[],b.num[]);
re.num[]=max(re.num[],a.R[]+b.L[]); re.num[]=max(re.num[],a.R[]+b.L[]);
re.sum[]=a.sum[]+b.sum[]; re.sum[]=a.sum[]+b.sum[];
if(a.da==) re.L[]=a.num[]+b.L[]; else if(a.da==) re.L[]=a.num[]+b.L[];
if(b.da==) re.R[]=b.num[]+a.R[]; else if(b.da==) re.R[]=b.num[]+a.R[];
if(a.da==b.da) re.da=a.da; else re.da=-;
return re;
}
inline void update(int now)
{
tree[now]=merge(tree[now<<],tree[now<<|]);
}
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;
tree[k].tag=-; tree[k].size=r-l+;
if(l==r)
{
scanf("%d",&tree[k].da);
if(tree[k].da)
{tree[k].L[]=tree[k].R[]=tree[k].num[]=tree[k].sum[]=;}
else
{tree[k].L[]=tree[k].R[]=tree[k].num[]=tree[k].sum[]=;}
return;
}
int mid=(l+r)>>;
build(k<<,l,mid);build(k<<|,mid+,r);
update(k);
}
inline void paintrev(int now)
{
swap(tree[now].L[],tree[now].L[]);
swap(tree[now].R[],tree[now].R[]);
swap(tree[now].num[],tree[now].num[]);
swap(tree[now].sum[],tree[now].sum[]);
if (tree[now].da!=-) tree[now].da^=;
}
inline void painttag(int now,int D)
{
tree[now].rev=;
if (D!=)
{
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=,
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=tree[now].size;
}
else
{
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=tree[now].size,
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=;
}
tree[now].da=D;
}
inline void pushdown(int now)
{
if (tree[now].l==tree[now].r) return;
if (tree[now].tag!=-)
{
tree[now<<].tag=tree[now<<|].tag=tree[now].tag;
painttag(now<<,tree[now].tag); painttag(now<<|,tree[now].tag); tree[now].tag=-;
}
if (tree[now].rev)
{
tree[now<<].rev^=; tree[now<<|].rev^=;
paintrev(now<<); paintrev(now<<|); tree[now].rev=;
}
}
inline void change(int now,int L,int R,int D)
{
pushdown(now);
if(tree[now].l==L && tree[now].r==R) {painttag(now,D);tree[now].tag=D;return;}
int mid=(tree[now].l+tree[now].r)>>;
if(mid>=R) change(now<<,L,R,D);
else if(mid<L) change(now<<|,L,R,D);
else change(now<<,L,mid,D),change(now<<|,mid+,R,D);
update(now);
}
inline void reserv(int now,int L,int R)
{
pushdown(now);
if(tree[now].l==L && tree[now].r==R) {paintrev(now);tree[now].rev^=;return;}
int mid=(tree[now].l+tree[now].r)>>;
if(mid>=R) reserv(now<<,L,R);
else if(mid<L) reserv(now<<|,L,R);
else reserv(now<<,L,mid),reserv(now<<|,mid+,R);
update(now);
}
inline int asksum(int now,int L,int R)
{
pushdown(now);
if(tree[now].l==L && tree[now].r==R) return tree[now].sum[];
int mid=(tree[now].l+tree[now].r)>>;
if(mid>=R) return asksum(now<<,L,R);
else if(mid<L) return asksum(now<<|,L,R);
else return asksum(now<<,L,mid)+asksum(now<<|,mid+,R);
update(now);
}
inline Treenode asknum(int now,int L,int R)
{
pushdown(now);
if (L==tree[now].l && R==tree[now].r) return tree[now];
int mid=(tree[now].l+tree[now].r)>>;
if (mid>=R) return asknum(now<<,L,R);
else if(mid<L)return asknum(now<<|,L,R);
else return merge(asknum(now<<,L,mid),asknum(now<<|,mid+,R));
}
int main()
{
n=read(),m=read();build(,,n);
while (m--)
{
int opt=read(),l=read(),r=read(); l++;r++;
switch (opt)
{
case : change(,l,r,);break;
case : change(,l,r,);break;
case : reserv(,l,r);break;
case : printf("%d\n",asksum(,l,r));break;
case : printf("%d\n",asknum(,l,r).num[]);break;
}
}
return ;
}
手一点误就调好久,巨恶心.. 自己讨论的不够好..还重敲了一遍....至于压代码?Char哥比我短80行..
【BZOJ-1858】序列操作 线段树的更多相关文章
- bzoj 2962 序列操作——线段树(卷积?)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 如果 _,_,_,…… 变成了 (_+k),(_+k),(_+k),…… ,计算就是在 ...
- bzoj 2962 序列操作 —— 线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 维护 sum[i] 表示选 i 个的乘积和,合并两个子树就枚举两边选多少,乘起来即可: ...
- bzoj 1858 序列操作
bzoj 1858 序列操作 带有随机多个区间单值覆盖的区间操作题,可考虑用珂朵莉树解决. #include<bits/stdc++.h> using namespace std; #de ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...
- 【BZOJ-2962】序列操作 线段树 + 区间卷积
2962: 序列操作 Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 678 Solved: 246[Submit][Status][Discuss] ...
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...
- 【BZOJ2962】序列操作 线段树
[BZOJ2962]序列操作 Description 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反 ...
- bzoj1858[Scoi2010]序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3079 Solved: 1475[Submit][Statu ...
随机推荐
- PAT 1015. 德才论 (25) JAVA
宋代史学家司马光在<资治通鉴>中有一段著名的"德才论":"是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得圣人,君子 ...
- BZOJ 1024 【SCOI2009】 生日快乐
Description windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕.现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋 ...
- Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to th ...
- jquery常用代码
转自:未找到 以下是jquery中比较常用的一些操作实现方式: $("标签名") //取html元素 document.getElementsByTagName("&qu ...
- java调用.net asmx / wcf
一.先用asmx与wcf写二个.net web service: 1.1 asmx web服务:asmx-service.asmx.cs using System; using System.Coll ...
- MYSQL查询优化
目前手头有个查询: SELECT LPP.learning_project_pupilID, SL.serviceID, MAX(LPPO.start_date), SUM(LPPOT.license ...
- Android开发:在EditText中关闭软键盘 转来的
1.EditText有焦点(focusable为true)阻止输入法弹出 editText=(EditText)findViewById(R.id.txtBody); editText.setOnTo ...
- 用Dart&Henson玩转Activity跳转
用Dart&Henson玩转Activity跳转 Extra是Android标准的组件之间(Activity/Fragment/Service等)传递数据的方式.本文介绍了开源项目Dart的使 ...
- 网站集成QQ登录功能
最近在做一个项目时,客户要求网站能够集成QQ登录的功能,以前没做过这方面的开发,于是去QQ的开放平台官网研究了一下相关资料,经过自己的艰苦探索,终于实现了集成QQ登录的功能,现在把相关的开发经验总结一 ...
- RabbitMQ官方中文入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)
发布/订阅 在上篇教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式被称为“ ...