您的位置:首页 > 产品设计 > UI/UE

HDU 3397 Sequence operation 线段树综合题

2017-07-21 15:03 519 查看
题目地址

题意:给你个01串,有以下几种操作。

0.把[l.r]区间的所有数都置为0.

1.把[l.r]区间的所有数都置为1.

2.把[l,r]区间的所有数都置为其相反数.

3.求[l,r]区间内的1的个数.

4.求[l,r]区间内的最长的连续的’1’的个数.

思路:这题我写了一天多了,还是发现是因为急躁好多小细节没有考虑清楚。其实这题适合于刚刚把线段树学完的人来写,因为都是一些基础的操作拼接起来的。题目本身并不难。我来先简要说下我的想法吧。我有两个延时更新标记,一个是覆盖0或者1的标记flag,如果是0操作就把该标记置为0,如果是1操作就把该标记置为1,另一个是判断是否取反的标记x_or(wa一天的点就是2操作是在update的时候忘记把当前标记与1做异或操作,直接给改标记赋1了,导致如果对同一个区间做取反操作2次的结果还是取反)。

操作修改情况:

如果是覆盖操作的话,无论x_or为多少直接置为0,然后再把flag置为相应的值。

如果是取反操作的话,先把x_or标记取反,再看如果flag不为-1,并且该x_or标记为1,则flag与1做异或操作,x_or置为0。

输出情况:

输出1的个数就是最简单的线段树的输出

输出该区间最长的连续1的序列(这个就是线段树的区间合并的知识,就是更新时还要加上个中间合并的区间会不会造成更长的连续区间)

附线段树模板:戳这里

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 100010
#define LL long long
#define inf 0x3f3f3f3f
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
using namespace std;
const LL mod = 1e9 + 7;
const double eps = 1e-9;
struct node {
int l, r;
int sum;//1的个数
int l0, r0, max0;
int l1, r1, max1;
int flag;//0,1覆盖标记
int x_or;//异或标记
}sum[N << 2];//线段树主体
struct Segment__Tree {
int x, y;
void pushUp(int ans) {
sum[ans].sum = sum[ans << 1].sum + sum[ans << 1 | 1].sum;
if (sum[ans << 1].l0 == (sum[ans << 1].r - sum[ans << 1].l + 1)) {
sum[ans].l0 = sum[ans << 1].l0 + sum[ans << 1 | 1].l0;
}
else {
sum[ans].l0 = sum[ans << 1].l0;
}
if (sum[ans << 1].l1 == (sum[ans << 1].r - sum[ans << 1].l + 1)) {
sum[ans].l1 = sum[ans << 1].l1 + sum[ans << 1 | 1].l1;
}
else {
sum[ans].l1 = sum[ans << 1].l1;
}
if (sum[ans << 1 | 1].r0 == (sum[ans << 1 | 1].r - sum[ans << 1 | 1].l + 1)) {
sum[ans].r0 = sum[ans << 1].r0 + sum[ans << 1 | 1].r0;
}
else {
sum[ans].r0 = sum[ans << 1 | 1].r0;
}
if (sum[ans << 1 | 1].r1 == (sum[ans << 1 | 1].r - sum[ans << 1 | 1].l + 1)) {
sum[ans].r1 = sum[ans << 1].r1 + sum[ans << 1 | 1].r1;
}
else {
sum[ans].r1 = sum[ans << 1 | 1].r1;
}
sum[ans].max0 = max(max(max(sum[ans << 1].max0, sum[ans << 1 | 1].max0), max(sum[ans].l0, sum[ans].r0)), sum[ans << 1].r0 + sum[ans << 1 | 1].l0);
sum[ans].max1 = max(max(max(sum[ans << 1].max1, sum[ans << 1 | 1].max1), max(sum[ans].l1, sum[ans].r1)), sum[ans << 1].r1 + sum[ans << 1 | 1].l1);
}
void pushDown(int ans) {
if (sum[ans].flag == 0) {
int l = sum[ans << 1].l;
int r = sum[ans << 1].r;
sum[ans << 1].sum = 0;
sum[ans << 1].l0 = r - l + 1;
sum[ans << 1].r0 = r - l + 1;
sum[ans << 1].max0 = r - l + 1;
sum[ans << 1].l1 = 0;
sum[ans << 1].r1 = 0;
sum[ans << 1].max1 = 0;
sum[ans << 1].flag = 0;
l = sum[ans << 1 | 1].l;
r = sum[ans << 1 | 1].r;
sum[ans << 1 | 1].sum = 0;
sum[ans << 1 | 1].l0 = r - l + 1;
sum[ans << 1 | 1].r0 = r - l + 1;
sum[ans << 1 | 1].max0 = r - l + 1;
sum[ans << 1 | 1].l1 = 0;
sum[ans << 1 | 1].r1 = 0;
sum[ans << 1 | 1].max1 = 0;
sum[ans << 1 | 1].flag = 0;
sum[ans << 1].x_or = 0;
sum[ans << 1 | 1].x_or = 0;
}
else if (sum[ans].flag == 1) {
int l = sum[ans << 1].l;
int r = sum[ans << 1].r;
sum[ans << 1].l0 = 0;
sum[ans << 1].r0 = 0;
sum[ans << 1].max0 = 0;
sum[ans << 1].sum = r - l + 1;
sum[ans << 1].l1 = r - l + 1;
sum[ans << 1].r1 = r - l + 1;
sum[ans << 1].max1 = r - l + 1;
sum[ans << 1].flag = 1;
l = sum[ans << 1 | 1].l;
r = sum[ans << 1 | 1].r;
sum[ans << 1 | 1].l0 = 0;
sum[ans << 1 | 1].r0 = 0;
sum[ans << 1 | 1].max0 = 0;
sum[ans << 1 | 1].sum = r - l + 1;
sum[ans << 1 | 1].l1 = r - l + 1;
sum[ans << 1 | 1].r1 = r - l + 1;
sum[ans << 1 | 1].max1 = r - l + 1;
sum[ans << 1 | 1].flag = 1;
sum[ans << 1].x_or = 0;
sum[ans << 1 | 1].x_or = 0;
}
if (sum[ans].x_or) {
int l = sum[ans << 1].l;
int r = sum[ans << 1].r;
sum[ans << 1].sum = r - l + 1 - sum[ans << 1].sum;
swap(sum[ans << 1].l0, sum[ans << 1].l1);
swap(sum[ans << 1].r0, sum[ans << 1].r1);
swap(sum[ans << 1].max0, sum[ans << 1].max1);
l = sum[ans << 1 | 1].l;
r = sum[ans << 1 | 1].r;
sum[ans << 1 | 1].sum = r - l + 1 - sum[ans << 1 | 1].sum;
swap(sum[ans << 1 | 1].l0, sum[ans << 1 | 1].l1);
swap(sum[ans << 1 | 1].r0, sum[ans << 1 | 1].r1);
swap(sum[ans << 1 | 1].max0, sum[ans << 1 | 1].max1);
sum[ans << 1].x_or ^= 1;
sum[ans << 1 | 1].x_or ^= 1;
}
sum[ans].flag = -1;
sum[ans].x_or = 0;
}
void build(int l, int r, int ans) {
sum[ans].l = l;
sum[ans].r = r;
sum[ans].flag = -1;
sum[ans].x_or = 0;
if (l == r) {
cin >> sum[ans].sum;
if (sum[ans].sum == 0) {
sum[ans].l0 = 1;
sum[ans].r0 = 1;
sum[ans].max0 = 1;
sum[ans].l1 = 0;
sum[ans].r1 = 0;
sum[ans].max1 = 0;
}
else {
sum[ans].l0 = 0;
sum[ans].r0 = 0;
sum[ans].max0 = 0;
sum[ans].l1 = 1;
sum[ans].r1 = 1;
sum[ans].max1 = 1;
}
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushUp(ans);
}
int solve(int l, int r, int ans, int nums) {
if (l >= x&&r <= y) {
if (nums) {
return sum[ans].max1;
}
return sum[ans].sum;
}
int mid = (l + r) >> 1;
pushDown(ans);
if (mid<x) {
return solve(rson, nums);
}
else if (mid >= y) {
return solve(lson, nums);
}
else {
if (nums) {
return max(max(solve(lson, nums), solve(rson, nums)), min(sum[ans << 1].r - x + 1, sum[ans << 1].r1) + min(y - sum[ans << 1 | 1].l + 1, sum[ans << 1 | 1].l1));
}
return solve(lson, nums) + solve(rson, nums);
}
}
void updata(int l, int r, int ans, int num) {
if (l >= x&&r <= y) {
if (num == 0) {
sum[ans].sum = 0;
sum[ans].l0 = r - l + 1;
sum[ans].r0 = r - l + 1;
sum[ans].max0 = r - l + 1;
sum[ans].l1 = 0;
sum[ans].r1 = 0;
sum[ans].max1 = 0;
sum[ans].flag = 0;
sum[ans].x_or = 0;
}
else if(num == 1){
sum[ans].sum = r - l + 1;
sum[ans].l0 = 0;
sum[ans].r0 = 0;
sum[ans].max0 = 0;
sum[ans].l1 = r - l + 1;
sum[ans].r1 = r - l + 1;
sum[ans].max1 = r - l + 1;
sum[ans].flag = 1;
sum[ans].x_or = 0;
}
else if (num == 2) {
sum[ans].sum = r - l + 1 - sum[ans].sum;
swap(sum[ans].l0, sum[ans].l1);
swap(sum[ans].r0, sum[ans].r1);
swap(sum[ans].max0, sum[ans].max1);
sum[ans].x_or ^= 1;
if (sum[ans].flag != -1 && sum[ans].x_or == 1) {
sum[ans].flag ^= 1;
sum[ans].x_or = 0;
}
}
return;
}
int mid = (l + r) >> 1;
pushDown(ans);
if (mid<x) {
updata(rson, num);
}
else if (mid >= y) {
updata(lson, num);
}
else {
updata(lson, num);
updata(rson, num);
}
pushUp(ans);
}
};
int main() {
cin.sync_with_stdio(false);
int c;
int s;
int n, q;
Segment__Tree tree;
int T;
cin >> T;
while (T--) {
cin >> n >> q;
tree.build(1, n, 1);
while (q--) {
cin >> s >> tree.x >> tree.y;
tree.x++;
tree.y++;
if (s == 0) {
tree.updata(1, n, 1, 0);
}
else if (s == 1) {
tree.updata(1, n, 1, 1);
}
else if (s == 2) {
tree.updata(1, n, 1, 2);
}
else if (s == 3) {
cout << tree.solve(1, n, 1, 0) << endl;
}
else {
cout << tree.solve(1, n, 1, 1) << endl;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: