HDU - 3911 Black And White 区间翻转+区间连续最长

2024-03-02 08:32

本文主要是介绍HDU - 3911 Black And White 区间翻转+区间连续最长,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

区间翻转的裸题,wrong了两发,没找bug,直接又打了一遍,这么大量的代码找bug是疯了。

重新开始做线段树的一些题了,感觉对于pushdown与lazy数组有点印象了。

首先,lazy数组是记录的当前数组的改变,不管是这个题的异或,还是加减,lazy数组就是线段树的主要优化原因,当你用的时候你再下放,大大减少了复杂度。但是记录的时候lazy[i]=1时候,tree[i]是要先处理的,然后每次每一查找的时候是先看该节点成不成立,不成立的话,再下放lazy。还有就是update的时候也要下放lazy.

就是这样,这道题的话主要的问题就是区间反转,lazy[i]变换两次的话就是不变,所以用异或来处理刚刚好,区间连续最长的问题就是个模板,记录左最长,右最长,总体最长。

1.在pushup的时候,要注意如果左儿子的左最长已经占了左边的总长,那么父亲节点的左最长就还要加上右儿子的左最长

父节点的右最长也是相同的

tree[i].wl=tree[lson].wl+((tree[lson].wl==mid-l+1)?tree[rson].wl:0);

2.第二个问题就是在query的时候,找的是左儿子的总体最长,右儿子总体最长,以及左儿子的右最长+右儿子的左最长在询问左端点ql,询问右端点qr之间的总长度。

 return max3(query(Lson,ql,mid),query(Rson,mid+1,qr),min(mid-ql+1,tree[lson].br)+min(qr-mid,tree[rson].bl));

结合全部代码,用宏定义,写起来会快很多还简

洁,但是可能会慢一点,理解理解。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1//左儿子
#define rson i<<1|1//右儿子
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
#define max4(a,b,c,d) max(max(a,b),max(c,d))
#define max3(x,y,z) max(max(x,y),max(y,z))
typedef long long ll;
using namespace std;
const int maxn=1e5+5;
struct node
{int wl,wr,wm,bl,br,bm;//w表示白的左,右,总;b就是black黑左右总
}tree[maxn<<2];
int lazy[maxn<<2];
int n,m;
void pushup(int i,int l,int r)//往上更新
{int mid=half;tree[i].wl=tree[lson].wl+((tree[lson].wl==mid-l+1)?tree[rson].wl:0);tree[i].bl=tree[lson].bl+((tree[lson].bl==mid-l+1)?tree[rson].bl:0);tree[i].wr=tree[rson].wr+((tree[rson].wr==r-mid)?tree[lson].wr:0);tree[i].br=tree[rson].br+((tree[rson].br==r-mid)?tree[lson].br:0);tree[i].wm=max3(tree[lson].wm,tree[rson].wm,tree[lson].wr+tree[rson].wl);tree[i].bm=max3(tree[lson].bm,tree[rson].bm,tree[lson].br+tree[rson].bl);
}
void change(int x)
{swap(tree[x].wl,tree[x].bl);swap(tree[x].wr,tree[x].br);swap(tree[x].wm,tree[x].bm);
}
void pushdown(int i,int l,int r)
{if(lazy[i]){lazy[lson]^=1;lazy[rson]^=1;change(lson);change(rson);lazy[i]=0;return;}
}
void update(int i,int l,int r,int ql,int qr)
{if(ql<=l&&qr>=r){change(i);lazy[i]^=1;return ;}int mid=half;pushdown(myself);if(qr<=mid) update(Lson,ql,qr);else if(ql>mid) update(Rson,ql,qr);else{update(Lson,ql,mid);update(Rson,mid+1,qr);}pushup(myself);
}
int query(int i,int l,int r,int ql,int qr)
{if(ql<=l&&qr>=r)return tree[i].bm;pushdown(myself);int mid=half;if(qr<=mid) return query(Lson,ql,qr);else if(ql>mid) return query(Rson,ql,qr);else return max3(query(Lson,ql,mid),query(Rson,mid+1,qr),min(mid-ql+1,tree[lson].br)+min(qr-mid,tree[rson].bl));
}
void build(int i,int l,int r)
{int x;lazy[i]=0;if(l==r){scanf("%d",&x);tree[i].bl=tree[i].br=tree[i].bm=x;tree[i].wl=tree[i].wr=tree[i].wm=x^1;return;}int mid=half;build(Lson);build(Rson);pushup(myself);
}
int main()
{int num,x,y;while(scanf("%d",&n)!=EOF){build(1,1,n);scanf("%d",&m);while(m--){scanf("%d%d%d",&num,&x,&y);if(num==0)printf("%d\n",query(1,1,n,x,y));elseupdate(1,1,n,x,y);}}return 0;
}

这篇关于HDU - 3911 Black And White 区间翻转+区间连续最长的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/765511

相关文章

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

关于最长递增子序列问题概述

《关于最长递增子序列问题概述》本文详细介绍了最长递增子序列问题的定义及两种优化解法:贪心+二分查找和动态规划+状态压缩,贪心+二分查找时间复杂度为O(nlogn),通过维护一个有序的“尾巴”数组来高效... 一、最长递增子序列问题概述1. 问题定义给定一个整数序列,例如 nums = [10, 9, 2

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while