P6492 [COCI2010-2011#6] STEP
题目描述
给定一个长度为
n
n
n 的字符序列
a
a
a,初始时序列中全部都是字符 L
。
有
q
q
q 次修改,每次给定一个
x
x
x,若
a
x
a_x
ax 为 L
,则将
a
x
a_x
ax 修改成 R
,否则将
a
x
a_x
ax 修改成 L
。
对于一个只含字符 L
,R
的字符串
s
s
s,若其中不存在连续的 L
和 R
,则称
s
s
s 满足要求。
每次修改后,请输出当前序列 a a a 中最长的满足要求的连续子串的长度。
输入格式
第一行有两个整数,分别表示序列的长度 n n n 和修改操作的次数 q q q。
接下来 q q q 行,每行一个整数,表示本次修改的位置 x x x。
输出格式
对于每次修改操作,输出一行一个整数表示修改 a a a 中最长的满足要求的子串的长度。
样例 #1
样例输入 #1
6 2
2
4
样例输出 #1
3
5
样例 #2
样例输入 #2
6 5
4
1
1
2
6
样例输出 #2
3
3
3
5
6
本题是这两题结合版245. 你能回答这些问题吗 AND P5057 [CQOI2006]简单题
单点修改,单点查询
对pos直接进行异或操作,题目要求的连续区间长度是连续间隔的01字符(不是连续的0或者连续的1),
构成答案的区间分两种情况讨论:跨区间与不跨区间,这样可以根据第一题的分类情况来实现oushu函数
void pushup(Node &u, Node &l, Node &r)
{
int mid = u.l + u.r >> 1;
int ls = mid - u.l + 1, rs = u.r - mid; // 左右区间大小
u.ans = max({l.ans, r.ans, l.lmax, r.rmax}), u.lmax = l.lmax, u.rmax = r.rmax;
if (a[mid] != a[mid + 1]) // 说明可以跨区间
{
u.ans = max(u.ans, l.rmax + r.lmax);
if (l.ans == ls) // 加入整个左儿子
u.lmax = ls + r.lmax;
if (r.ans == rs) // 加入整个右儿子
u.rmax = rs + l.rmax;
}
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
完整代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <climits>
#include <unordered_map>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define mst(x, y) memset(x, y, sizeof x)
#define X first
#define Y second
#define int long long
#define Lson u << 1, l, mid
#define Rson u << 1 | 1, mid + 1, r
#define FAST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 200010, INF = 0x3f3f3f3f3f3f3f3f, MOD = 1e9 + 7;
const double EPS = 1e-6;
typedef pair<int, int> PII;
typedef unordered_map<int, int> Ump;
int T;
int n, m;
int a[N];
struct Node
{
int l, r;
int ans;
int lmax, rmax;
} tr[N << 2];
void pushup(Node &u, Node &l, Node &r)
{
int mid = u.l + u.r >> 1;
int ls = mid - u.l + 1, rs = u.r - mid;
u.ans = max({l.ans, r.ans, l.lmax, r.rmax}), u.lmax = l.lmax, u.rmax = r.rmax;
if (a[mid] != a[mid + 1])
{
u.ans = max(u.ans, l.rmax + r.lmax);
if (l.ans == ls)
u.lmax = ls + r.lmax;
if (r.ans == rs)
u.rmax = rs + l.rmax;
}
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
if (l == r)
tr[u] = {r, r, 1, 1, 1};
else
{
tr[u] = {l, r};
int mid = l + r >> 1;
build(Lson), build(Rson);
pushup(u);
}
}
void modify(int u, int x)
{
if (tr[u].l == x && tr[u].r == x)
a[x] ^= 1;
else
{
int mid = tr[u].l + tr[u].r >> 1;
if (x <= mid)
modify(u << 1, x);
else
modify(u << 1 | 1, x);
pushup(u);
}
}
void solve()
{
cin >> n >> m;
build(1, 1, n);
int pos;
while (m--)
{
cin >> pos;
modify(1, pos);
cout << tr[1].ans << endl;
}
}
signed main()
{
FAST;
// cin >> T;
T = 1;
while (T--)
solve();
return 0;
}