洛谷 P6492 [COCI2010-2011#6] STEP
题目
题目描述
给定一个长度为 nn 的字符序列 aa,初始时序列中全部都是字符 L
。
有 qq 次修改,每次给定一个 xx,若 a_xax 为 L
,则将 a_xax 修改成 R
,否则将 a_xax 修改成 L
。
对于一个只含字符 L
,R
的字符串 ss,若其中不存在连续的 L
和 R
,则称 ss 满足要求。
每次修改后,请输出当前序列 aa 中最长的满足要求的连续子串的长度。
输入格式
第一行有两个整数,分别表示序列的长度 nn 和修改操作的次数 qq。
接下来 qq 行,每行一个整数,表示本次修改的位置 xx。
输出格式
对于每次修改操作,输出一行一个整数表示修改 aa 中最长的满足要求的子串的长度。
输入输出样例
输入 #1
6 2 2 4
输出 #1
3 5
输入 #2
6 5 4 1 1 2 6
输出 #2
3 3 3 5 6
说明/提示
数据规模与约定
对于全部的测试点,保证 1≤n,q≤2×105,1 ≤ x ≤ n。
说明
题目译自 COCI2010-2011 CONTEST #6 T5 STEP,翻译来自 @一扶苏一。
思考
这个题其实和区间和区别并不大,只是把求和的push_up操作改为求最长的连续符合条件的串即可。
分左,中,右三部分考虑。
代码
#include <bits/stdc++.h> using namespace std; inline long long read() { long long x = 0; int f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } return x * f; } void write(const int& x) { if (!x) { putchar('0'); return; } char f[100]; int tmp = x; if (tmp < 0) { tmp = -tmp; putchar('-'); } int s = 0; while (tmp > 0) { f[s++] = tmp % 10 + '0'; tmp /= 10; } while (s > 0) { putchar(f[--s]); } } const int MAXN = 1000090; bool nums[MAXN]; long long totN; long long totDO; struct Node { long long lvalue; long long rvalue; long long midvalue; long long l, r; Node* lch, * rch; inline void push_up() { lvalue=lch->lvalue; rvalue=rch->rvalue; if (nums[lch->r]!=nums[rch->l]) { if (lch->lvalue==(lch->r-lch->l+1)) { lvalue+=rch->lvalue; } if (rch->rvalue==(rch->r-rch->l+1)) { rvalue+=lch->rvalue; } } midvalue=max(nums[lch->r]!=nums[rch->l]?lch->rvalue+rch->lvalue:0,max(lch->midvalue,rch->midvalue)); } Node(const long long L, const long long R) { l = L; r = R; if (l==r) { lch = NULL; rch = NULL; lvalue=rvalue=midvalue=1; } else { long long mid = (l + r) >> 1; lch = new Node(L, mid); rch = new Node(mid + 1, R); push_up(); } } inline void update(const long long w) { if (l==r) { return; } if (lch->r>=w) { lch->update(w); } else { rch->update(w); } push_up(); } }; int main() { totN=read(); totDO=read(); Node *root=new Node(1,totN); for (int i = 1; i <= totDO; ++i) { auto tempX=read(); nums[tempX]^=1; root->update(tempX); write(root->midvalue); putchar('\n'); } return 0; }//LikiBlaze Code