题目链接 [Scoi2010]序列操作

考验代码能力的一道好题。

思想还是很简单的(直接上线段树),但是比较难写。

#include <bits/stdc++.h>

using namespace std;

#define REP(i,n)                for(int i(0); i <  (n); ++i)
#define rep(i,a,b) for(int i(a); i <= (b); ++i)
#define dec(i,a,b) for(int i(a); i >= (b); --i)
#define for_edge(i,x) for(int i = H[x]; i; i = X[i]) #define LL long long
#define ULL unsigned long long
#define MP make_pair
#define PB push_back
#define FI first
#define SE second
#define INF 1 << 30 const int N = 200000 + 10;
const int M = 10000 + 10;
const int Q = 1000 + 10;
const int A = 30 + 1; struct segTree{
int len;
int maxn[2], lmax[2], rmax[2], sum[2];
} segtree[N << 2]; int a[N], de_cover[N << 2], de_turn[N << 2];
int n, m, op, x, y; segTree update(segTree x, segTree y){
segTree ans;
ans.len = x.len + y.len;
rep(i, 0, 1){
ans.sum[i] = x.sum[i] + y.sum[i];
ans.lmax[i] = (x.lmax[i] == x.len ? x.len + y.lmax[i] : x.lmax[i]);
ans.rmax[i] = (y.rmax[i] == y.len ? x.rmax[i] + y.len : y.rmax[i]);
ans.maxn[i] = max(max(x.maxn[i], y.maxn[i]), max(ans.lmax[i], ans.rmax[i]));
ans.maxn[i] = max(ans.maxn[i], x.rmax[i] + y.lmax[i]);
} return ans;
} void build(int i, int l, int r){
if (l == r){
int z = a[l];
segtree[i].len = segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = 1;
segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = 0;
de_cover[i] = -1, de_turn[i] = 0;
return ;
} int mid = (l + r) >> 1;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]);
de_cover[i] = -1, de_turn[i] = 0;
} void paint_cover(int i, int z){
de_cover[i] = z;
de_turn[i] = 0;
segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = segtree[i].len;
segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = 0;
} void paint_turn(int i, int z){
if (z != -1){
de_cover[i] ^= 1;
segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = 0;
segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = segtree[i].len;
}
else{
de_turn[i] ^= 1;
swap(segtree[i].sum[0], segtree[i].sum[1]);
swap(segtree[i].lmax[0], segtree[i].lmax[1]);
swap(segtree[i].rmax[0], segtree[i].rmax[1]);
swap(segtree[i].maxn[0], segtree[i].maxn[1]);
}
} void pushdown(int i){
if (de_cover[i] != -1){
paint_cover(i << 1, de_cover[i]);
paint_cover(i << 1 | 1, de_cover[i]);
de_cover[i] = -1;
}
if (de_turn[i]){
paint_turn(i << 1, de_cover[i << 1]);
paint_turn(i << 1 | 1, de_cover[i << 1 | 1]);
de_turn[i] = 0;
}
} void insert_cover(int i, int l, int r, int x, int y, int z){
if (x <= l && y >= r){
paint_cover(i, z);
return ;
} pushdown(i);
int mid = (l + r) >> 1;
if (x <= mid) insert_cover(i << 1, l, mid, x, y, z);
if (y > mid) insert_cover(i << 1 | 1, mid + 1, r, x, y, z);
segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]);
} void insert_turn(int i, int l, int r, int x, int y){
if (x <= l && y >= r){
paint_turn(i, de_cover[i]);
return ;
} pushdown(i);
int mid = (l + r) >> 1;
if (x <= mid) insert_turn(i << 1, l, mid, x, y);
if (y > mid) insert_turn(i << 1 | 1, mid + 1, r, x, y);
segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]);
} int query_sum(int i, int l, int r, int x, int y){
int sum = 0;
if (x <= l && y >= r){ return segtree[i].sum[1];}
int mid = (l + r) >> 1;
pushdown(i);
if (x <= mid) sum += query_sum(i << 1, l, mid, x, y);
if (y > mid) sum += query_sum(i << 1 | 1, mid + 1, r, x, y);
return sum;
} segTree query_con(int i, int l ,int r, int x, int y){
segTree ans1, ans2;
bool f1 = false, f2 = false;
if (x <= l && y >= r) return segtree[i];
pushdown(i); int mid = (l + r) >> 1;
if (x <= mid) ans1 = query_con(i << 1, l, mid, x, y), f1 = true;
if (y > mid) ans2 = query_con(i << 1 | 1, mid + 1, r, x, y), f2 = true;
if (f1 && f2) return update(ans1, ans2);
else return f1 ? ans1 : ans2;
} int main(){ scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%d", a + i);
build(1, 1, n);
while (m--){
scanf("%d%d%d", &op, &x, &y);
++x, ++y;
if (op == 0) insert_cover(1, 1, n, x, y, 0);
if (op == 1) insert_cover(1, 1, n, x, y, 1);
if (op == 2) insert_turn(1, 1, n, x, y);
if (op == 3) printf("%d\n", query_sum(1, 1, n, x, y));
if (op == 4) printf("%d\n", query_con(1, 1, n, x, y).maxn[1]);
} return 0; }

BZOJ1858 [Scoi2010]序列操作(线段树)的更多相关文章

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

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

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858 线段树...调了一个上午...(后面带 // 的都是改出来的) lazy 标记的下放好 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Codeforces Round #464 (Div. 2) A Determined Cleanup

    A. Love Triangle time limit per test1 second memory limit per test256 megabytes Problem Description ...

  2. 其它- in-place

    in-place 刷编程题的时候,经常遇到题目要求do in-place.所以就上网搜了相关概念,简单总结一下.   in-place操作,意思是所有的操作都是”就地“操作,不允许进行移动,或者称作  ...

  3. windows server 2008解决无法PING通问题

    今天安装服务器(server 2008),配置完IP地址后,发现局域网其它电脑无法PING通服务器,测线仪测试链路都正常,网线接别的电脑也正常,以为是网卡问题,于是ping了自己的IP,发现能PING ...

  4. 《Scrum实战》第4次课【全职的Scrum Master】作业汇总

    1组: 孟帅 http://www.cnblogs.com/mengshuai1982/p/7375008.html 3组: 张亚辉 http://www.jianshu.com/p/df9eee08 ...

  5. IOS开发---菜鸟学习之路--(十二)-利用ASIHTTPRequest进行异步获取数据

    想要实现异步获取的话我这边了解过来有两个非常简单的方式 一个是利用ASIHTTPRequest来实现异步获取数据 另一个则是利用MBProgressHUD来实现异步获取数据 本章就先来讲解如何利用AS ...

  6. STL学习笔记3--deque

    看这一节,是为了下一节的使用,在ogre3d里有些操作要使用到deque. C++ Deque(双向队列) 的使用 Deque结合了vector  和list  优缺点,是一种使用简单的容器. deq ...

  7. Robotium之Android控件定位实践和建议

    本人之前曾经撰文描述Appium和UIAutomator框架是如何定位Android界面上的控件的. UIAutomator定位Android控件的方法实践和建议Appium基于安卓的各种FindEl ...

  8. Leetcode 560.和为k的子数组

    和为k的子数组 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1 ...

  9. leetcode NO.1 两数之和 (python实现)

    来源 https://leetcode-cn.com/problems/two-sum/description/ 题目描述 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个 ...

  10. web项目中各种路径的获取(复制,为以后好找资源)

    web项目中各种路径的获取 1.可以在servlet的init方法里 String path = getServletContext().getRealPath("/"); 这将获 ...