4 L R 询问[L,R]之间连续1的个数最大是多少.
第一眼:这sb题。。
第二眼:这sb题。。
第三眼:哎呀卧槽这儿取反和赋值俩标记咋搞???
大致脑补了一下,很不确定对不对,然后上网看了下别人的写法,也觉得很难想清楚。。
管他的,开始写吧!!
用啥数据结构?线段树?貌似很好写,但是线段树修改都还好,最要命的是询问的时候你还得拼凑答案。
那就treap吧。。treap可以split出来直接读取答案。
写了差不多40分钟终于写出来了,样例1A了。然后往codevs上叫只过了一个点。。
然后就开始2+hrs的Debug。。然后实在找不出错了。。然后就打算另辟蹊径,我不维护两个标记了,我直接维护两个treap!!空间没限制就是任性!!这两个treap每一位都相反,比如说第一个treap是01001,第二个就是10110,各自维护对应的信息,分开保存根。
每次题目要求<0 l r>操作的时候实际对第一个treap进行<0 l r>,对第二个进行<1 l r>;
操作<1 l r>类似;
每次题目要求<2 l r>操作的时候交换两个treap的[l,r]区间即可。
然后就只需要保存一个same标记啦!!!
然后就慢死了。。。常数略大。。。bzoj上跑了9s+。。
但是我觉得这种思路真的很实用!!!像这道题这样按位取反,还有经典的区间翻转都能用这种维护两个序列的方式来实现,从而避免多个懒标记下传顺序的讨论。更准确的说,如果一个操作连续对[l,r]作用两次后会恢复原状,就可以用这种方法。虽然牺牲一点常数时间,但是准确率大大提高了。。这种方法treap和splay都可以实现,但好像线段树不好做。
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<cassert> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #define erp(i,a,b) for(int i=a;i>=b;--i) #define LL long long typedef pair<int, int> pii; const int MAXN = 100005*2; #define fi first #define se second int N, M; inline int ran() { static int sd = 1237; return sd = (sd*12371237)&0x7fffffff; } struct Treap { int lch[MAXN], rch[MAXN], sz[MAXN], fix[MAXN]; int xt[MAXN], cnt[MAXN], val[MAXN]; int lx[MAXN][2], rx[MAXN][2], mx[MAXN][2]; int ncnt, r1, r2; //建两棵相反的treap来避免reverse标记 int L, R, flag; inline void pushup(int x) { L = lch[x], R = rch[x]; sz[x] = sz[L] + sz[R] + 1; cnt[x] = cnt[L] + cnt[R] + val[x]; rep(c, 0, 1) { flag = (val[x]==c); if (mx[L][c] == sz[L]) lx[x][c] = sz[L] + flag + lx[R][c]*flag; else lx[x][c] = lx[L][c]; if (mx[R][c] == sz[R]) rx[x][c] = sz[R] + flag + rx[L][c]*flag; else rx[x][c] = rx[R][c]; mx[x][c] = max(mx[L][c], mx[R][c]); if (flag) mx[x][c] = max(mx[x][c], rx[L][c]+1+lx[R][c]); } } inline void upxt(int x, int v) { if (!x) return; cnt[x] = (val[x]=v) * sz[x]; lx[x][v] = rx[x][v] = mx[x][v] = sz[x]; lx[x][!v] = rx[x][!v] = mx[x][!v] = 0; xt[x] = v; } inline void pushdown(int x) { L = lch[x], R = rch[x]; if (~xt[x]) { upxt(L, xt[x]), upxt(R, xt[x]); xt[x] = -1; } } int NewNode(int i) { ++ncnt; fix[ncnt] = ran(); cnt[ncnt] = val[ncnt] = i; sz[ncnt] = 1; lx[ncnt][i] = rx[ncnt][i] = mx[ncnt][i] = 1; xt[ncnt] = -1; return ncnt; } int merge(int a, int b) { if (!a || !b) return a|b; pushdown(a), pushdown(b); if (fix[a] > fix[b]) { rch[a] = merge(rch[a], b); return pushup(a), a; } else { lch[b] = merge(a, lch[b]); return pushup(b), b; } } pii split(int x, int k) { if (!x) return pii(0, 0); pushdown(x); pii y; if (sz[lch[x]] >= k) { y = split(lch[x], k); lch[x] = y.se, y.se = x; } else { y = split(rch[x], k - sz[lch[x]] - 1); rch[x] = y.fi, y.fi = x; } return pushup(x), y; } int sta[MAXN]; int build(int*a, int n) { int x, las, p = 0; rep(i, 1, n) { x = NewNode(a[i]); las = 0; while (p && fix[sta[p]] < fix[x]) pushup(las = sta[p]), sta[p--] = 0; if (p) rch[sta[p]] = x; lch[x] = las; sta[++p] = x; } while (p) pushup(sta[p--]); return sta[1]; } void init(int*a, int n) { r1 = build(a, n); rep(i, 1, n) a[i] ^= 1; r2 = build(a, n); } void makesame(int l, int r, int v) { pii t1 = split(r1, l-1); pii t2 = split(t1.se, r-l+1); upxt(t2.fi, v); r1 = merge(merge(t1.fi, t2.fi), t2.se); t1 = split(r2, l-1); t2 = split(t1.se, r-l+1); upxt(t2.fi, !v); r2 = merge(merge(t1.fi, t2.fi), t2.se); } void reverse(int l, int r) { pii t1 = split(r1, l-1); pii t2 = split(t1.se, r-l+1); pii t3 = split(r2, l-1); pii t4 = split(t3.se, r-l+1); r1 = merge(merge(t1.fi, t4.fi), t2.se); r2 = merge(merge(t3.fi, t2.fi), t4.se); } int qcnt(int l, int r) { pii t1 = split(r1, l-1); pii t2 = split(t1.se, r-l+1); int ans = cnt[t2.fi]; r1 = merge(merge(t1.fi, t2.fi), t2.se); return ans; } int qmx(int l, int r) { pii t1 = split(r1, l-1); pii t2 = split(t1.se, r-l+1); int ans = mx[t2.fi][1]; r1 = merge(merge(t1.fi, t2.fi), t2.se); return ans; } } tp; int s[MAXN]; int main() { freopen("data.txt", "r", stdin); freopen("f.out", "w", stdout); scanf("%d%d", &N, &M); rep(i, 1, N) scanf("%d", s+i); tp.init(s, N); int op, l, r; while (M --) { scanf("%d%d%d", &op, &l, &r); l++, r++; switch(op) { case 0: tp.makesame(l, r, 0); break; case 1: tp.makesame(l, r, 1); break; case 2: tp.reverse(l, r); break; case 3: printf("%d\n", tp.qcnt(l, r)); break; default:printf("%d\n", tp.qmx(l, r)); break; } } return 0; }