http://acm.hust.edu.cn/vjudge/problem/14689

三个操作

  1. [a,b]覆盖为0
  2. [a,b]覆盖为1
  3. [a,b]颠倒每项

两个查询

  1. [a,b]间1数量
  2. [a,b]间最长连续1数量

其实是区间覆盖,区间颠倒和区间合并的结合,可以先看这几道题

区间合并:http://www.cnblogs.com/qlky/p/5745065.html

区间更新(两种更新方式):http://www.cnblogs.com/qlky/p/5737676.html

可以分为两项做:

1的数量很简单,用len[]保存每个区间数量即可

[a,b]区间内最长连续其实之前没做过,具体做法是:

在区间合并的基础上,在query时取左子树,右子树以及min(mid-L+1,rsum[ls])+min(R-mid,lsum[rs])的最小值

这里的min(mid-L+1,rsum[ls])+min(R-mid,lsum[rs])其实就是左子树的右端和右子树左端结合,前面那项是为了限定左右的最大值,因为要在选定的区间内找连续值

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std; #define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!\n")
#define MAXN 100000+5
#define MAX(a,b) a>b?a:b
#define blank pf("\n")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f #define ls (rt<<1)
#define rs (rt<<1|1) int n,m; int col[MAXN<<],a[MAXN<<],len[MAXN<<]; int sum[MAXN<<],lsum[MAXN<<],rsum[MAXN<<],mz[MAXN<<],lz[MAXN<<],rz[MAXN<<]; void cg(int &a,int &b)
{
int tmp = a;
a = b;
b = tmp;
} void FXOR(int rt,int k)
{
//pf("xor%d %d %d %d t%d %d %d\n",rt,sum[rt],lsum[rt],rsum[rt],mz[rt],lz[rt],rz[rt]);
//统计1数量
len[rt] = k-len[rt]; //最长连续1
cg(sum[rt],mz[rt]);
cg(lsum[rt],lz[rt]);
cg(rsum[rt],rz[rt]);
//pf("xor%d %d %d %d t%d %d %d\n",rt,sum[rt],lsum[rt],rsum[rt],mz[rt],lz[rt],rz[rt]);
if(a[rt]!= -)
{
a[rt]^=;
}
else col[rt]^=;
} void PushDown(int rt,int l,int r)
{
if(l==r) return;
int mid = (l+r)>>;
if(a[rt]!=-)
{
//统计1数量
a[ls] = a[rt]?a[rt]:;
a[rs] = a[rt]?a[rt]:;
len[rs] = a[rt]?(r-mid):;
len[ls] = a[rt]?(mid-l+):;
//最长连续1
sum[rs] = lsum[rs] = rsum[rs] = a[rt]?(r-mid):;
sum[ls] = lsum[ls] = rsum[ls] = a[rt]?(mid-l+):;
mz[rs] = lz[rs] = rz[rs] = a[rt]?:(r-mid);
mz[ls] = lz[ls] = rz[ls] = a[rt]?:(mid-l+); col[rt] = ;
a[rt] = -;
}
if(col[rt])
{
if(l!=r)
{
FXOR(ls,mid-l+);
FXOR(rs,r-mid);
}
col[rt] = ;
}
} void PushUp(int rt,int k)
{
if(k==) return;
//最长连续1
lsum[rt] = lsum[ls];
lz[rt] = lz[ls];
rsum[rt] = rsum[rs];
rz[rt] = rz[rs];
if(lsum[rt]==k-(k>>)) lsum[rt]+=lsum[rs];
if(rsum[rt]==k>>) rsum[rt]+=rsum[ls];
if(lz[rt]==k-(k>>)) lz[rt]+=lz[rs];
if(rz[rt]==k>>) rz[rt]+=rz[ls];
sum[rt] = max(lsum[rs]+rsum[ls],max(sum[rs],sum[ls]));
mz[rt] = max(lz[rs]+rz[ls],max(mz[rs],mz[ls]));
//统计1数量
len[rt] = len[rs]+len[ls];
} void build(int l,int r,int rt)
{
a[rt] = -;
sum[rt] = lsum[rt] = rsum[rt] = len[rt] = col[rt] = ;
mz[rt] = lz[rt] = rz[rt] = r-l+;
if(l==r) return;
int mid = (l+r)>>;
build(l,mid,ls);
build(mid+,r,rs);
} void update(int val,int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)
{
if(val==)
{
//统计1数量
len[rt] = a[rt] = col[rt] = ; //统计最长连续1
sum[rt] = rsum[rt] = lsum[rt] = ;
mz[rt] = rz[rt] = lz[rt] = r-l+;
}
else if(val==)
{
//统计1数量
len[rt] = r-l+;
a[rt] = ;
col[rt] = ; //统计最长连续1
sum[rt] = rsum[rt] = lsum[rt] = r-l+;
mz[rt] = rz[rt] = lz[rt] = ;
}
else
{
FXOR(rt,r-l+);
}
return;
}
PushDown(rt,l,r);
int mid = (l+r)>>;
if(L <= mid) update(val,L,R,l,mid,ls);
if(R > mid) update(val,L,R,mid+,r,rs);
PushUp(rt,r-l+);
} LL ans = ; //统计1数量
void query(int L,int R,int l,int r,int rt)
{
//pf("%d %d %d %d\n",L,R,l,r);
if(L <= l && r <= R)
{
ans+=len[rt];
return;
}
PushDown(rt,l,r);
int mid = (l+r)>>;
if(L<=mid) query(L,R,l,mid,ls);
if(R>mid) query(L,R,mid+,r,rs);
} //最长连续1
int query2(int L,int R,int l,int r,int rt)
{
//pf("%d %d %d %d\n",L,R,l,r);
if(L <= l && r <= R)
{
return sum[rt];
}
PushDown(rt,l,r);
int res = ;
int mid = (l+r)>>;
if(L<=mid)
{
int tmp = query2(L,R,l,mid,ls);
res = max(tmp,res);
}
if(R>mid)
{
int tmp = query2(L,R,mid+,r,rs);
res = max(tmp,res);
}
res = max(res,min(mid-L+,rsum[ls])+min(R-mid,lsum[rs]));
return res;
} int main()
{
int n,i,j,t,kase=;
sf("%d",&t);
while(t--)
{
sf("%d%d",&n,&m);
build(,n,);
for(i=;i<=n;i++)
{
int tmp;
sf("%d",&tmp);
update(tmp,i,i,,n,);
}
//for(i=1;i<=18;i++) pf("t%d %d %d %d\n",i,sum[i],lsum[i],rsum[i]);
//for(i=1;i<=18;i++) pf("t%d %d %d %d\n",i,mz[i],lz[i],rz[i]);
for(i=;i<=m;i++)
{
int tmp,c,d;
sf("%d%d%d",&tmp,&c,&d);
if(tmp==) update(,c+,d+,,n,);
else if (tmp==) update(,c+,d+,,n,);
else if(tmp==) update(,c+,d+,,n,);
else if(tmp==)
{
ans = ;
query(c+,d+,,n,);
pf("%I64d\n",ans);
}
else
{
pf("%d\n",query2(c+,d+,,n,));
}
//for(j=1;j<=18;j++) pf("t%d %d %d %d t%d %d\n",j,sum[j],lsum[j],rsum[j],a[j],col[j]);
//for(j=1;j<=18;j++) pf("tt%d %d %d %d\n",j,mz[j],lz[j],rz[j]);
}
}
return ;
}
/*
1
10 1000
0 0 0 1 1 0 1 0 1 1
3 0 0
3 1 1
3 2 2
3 3 3
3 4 4
3 5 5
3 6 6
3 7 7
3 8 8
3 9 9
3 0 0
3 0 1
3 0 2
3 0 3
3 0 4
3 0 5
3 0 6
3 0 7
3 0 8
3 0 9
*/

HDU 3397 区间覆盖,颠倒,合并(好题)的更多相关文章

  1. 贪心算法----区间覆盖问题(POJ2376)

    题目: 题目的大概意思是约翰这个农民有N条牛,这些牛可以在一天中的某个时间段可以进行工作,他想把这个时间段分成若干个片段让这些牛去进行打扫任务,你的任务是安排尽量少的牛然后可以完成分成这些片段的打扫任 ...

  2. UVA 10382 Watering Grass(区间覆盖,贪心)题解

    题意:有一块草坪,这块草坪长l 米,宽 w 米,草坪有一些喷头,每个喷头在横坐标为 p 处,每个喷头的纵坐标都是(w/2) ,并且喷头的洒水范围是一个以喷头为圆心,半径为 r 米的圆.每次最少需要打开 ...

  3. POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并

    看到讲课安排上 线段树有一节课"区间合并" 我是迷茫的 因为并没有见过 然后了解了一下题目 发现以前写过 还是很麻烦的树链剖分 大概是 解决带修改的区间查询"连续问题&q ...

  4. (简单) HDU 3397 Sequence operation,线段树+区间合并。

    Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...

  5. HDU 4509 湫湫系列故事——减肥记II(线段树-区间覆盖 或者 暴力技巧)

    http://acm.hdu.edu.cn/showproblem.php?pid=4509 题目大意: 中文意义,应该能懂. 解题思路: 因为题目给的时间是一天24小时,而且还有分钟.为了解题方便, ...

  6. 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)

    HDU 5861 题意 在n个村庄之间存在n-1段路,令某段路开放一天需要交纳wi的费用,但是每段路只能开放一次,一旦关闭将不再开放.现在给你接下来m天内的计划,在第i天,需要对村庄ai到村庄bi的道 ...

  7. Tunnel Warfare HDU 1540 区间合并+最大最小值

    Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里 ...

  8. 牛客挑战赛40 VMware和基站 set 二分 启发式合并 区间覆盖

    LINK:VMware和基站 一道 做法并不常见的题目 看起来很难写 其实set维护线段就可以解决了. 容易想到 第二个操作借用启发式合并可以得到一个很不错的复杂度 不过利用线段树维护这个东西 在区间 ...

  9. HDU - 3974 Assign the task (DFS建树+区间覆盖+单点查询)

    题意:一共有n名员工, n-1条关系, 每次给一个人分配任务的时候,(如果他有)给他的所有下属也分配这个任务, 下属的下属也算自己的下属, 每次查询的时候都输出这个人最新的任务(如果他有), 没有就输 ...

随机推荐

  1. [原创]ObjectARX开发环境搭建之VS2010+ObjectARX2012Wizard+Addin工具条问题修复

    目前ObjectARX版本越来越高,也越来越简化开发,如果需要同时开发低版本和高版本的ARX程序,就需要搭建批量编译环境,以满足ARX开发的需要. 批量编译的搭建网络上已经有了很多的教程,基本上都是基 ...

  2. 伪元素改变date类型input框的默认样式实例页面

    CSS代码: ::-webkit-datetime-edit { padding: 1px; background: url(/study/image/selection.gif); } ::-web ...

  3. Python开发MapReduce系列(一)WordCount Demo

    原创,转发请注明出处. MapReduce是hadoop这只大象的核心,Hadoop 中,数据处理核心就是 MapReduce 程序设计模型.一个Map/Reduce 作业(job) 通常会把输入的数 ...

  4. sublime text3文本字体大小设置

    1.perferences->settings-user 4·将以下代码粘贴进入即可 { "font_face": "source code pro, " ...

  5. bzoj1221软件开发 费用流

    题目传送门 思路: 网络流拆点有的是“过程拆点”,有的是“状态拆点”,这道题应该就属于状态拆点. 每个点分需要用的,用完的. 对于需要用的,这些毛巾来自新买的和用过的毛巾进行消毒的,流向终点. 对于用 ...

  6. 114th LeetCode Weekly Contest Array of Doubled Pairs

    Given an array of integers A with even length, return true if and only if it is possible to reorder ...

  7. Win10安装MySQL5.7.22解压缩版的方法及手动配置讲解

    1.先去MYSQL官网下载安装包,解压放到C盘 2.新建一个my.ini文件放到bin文件夹下面,内容如下,路径对应自己的安装目录: [mysql] # 设置mysql客户端默认字符集 default ...

  8. js面向切面编程

    Function.prototype.before=function(func){ var _self=this; return function(){  if(func.apply(this,arg ...

  9. 剑指offer——面试题8:二叉树的下一个节点

    // 面试题8:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针. ...

  10. java将文本写入本地硬盘

    注意:首先要在E盘创建qaz.txt文本文件.然后执行代码写入. public static void main(String[] args) { SecurityCodeUtils scu = ne ...