BZOJ2002 [HNOI2010]Bounce 弹飞绵羊
2018-02-04 19:41
267 查看
Address
洛谷P3203 BZOJ2002Solution
LCTLCT 模板题……因为原图无环,把位置看做 nn 个点,用 LCTLCT 维护各点 szesze (子树大小)。
新增一个表示被弹飞的点 n+1n+1,则对于位置 ii :
若 i+ki≤ni+ki≤n,连边 (i,i+ki)(i,i+ki)
若 i+ki>ni+ki>n,连边 (i,n+1)(i,n+1)
对于初始时的 kiki 先连接上边
对于修改操作:断开原来的边再连接上新的边
对于询问操作:取出 LCTLCT 中 ii ~ n+1n+1 的实路径,输出顶部节点szesze
时间复杂度 均摊O(nlogn)O(nlogn)
Code
#include <iostream> #include <cstdio> #include <cctype> #include <algorithm> #include <cstring> using namespace std; namespace inout { const int S = 1 << 20; char frd[S], *ihed = frd + S; const char *ital = ihed; inline char inChar() { if (ihed == ital) fread(frd, 1, S, stdin), ihed = frd; return *ihed++; } inline int get() { char ch; int res = 0; bool flag = false; while (!isdigit(ch = inChar()) && ch != '-'); (ch == '-' ? flag = true : res = ch ^ 48); while (isdigit(ch = inChar())) res = res * 10 + ch - 48; return flag ? -res : res; } char fwt[S], *ohed = fwt; const char *otal = fwt + S; inline char outChar(char ch) { if (ohed == otal) fwrite(fwt, 1, S, stdout), ohed = fwt; return *ohed++ = ch; } inline void put(int x) { if (x > 9) put(x / 10); outChar(x % 10 + 48); } }; using namespace inout; const int N = 2e5 + 5; int n, m, k ; inline int Min(int x, int y) {return x < y ? x : y;} namespace LCT { int lc , rc , fa , sze , rev ; int qr, que ; inline bool Which(int x) { return lc[fa[x]] == x; } inline bool isRoot(int x) { return !fa[x] || lc[fa[x]] != x && rc[fa[x]] != x; } inline bool Uptdate(int x) { sze[x] = sze[lc[x]] + sze[rc[x]] + 1; } inline void pushDown(int x) { if (rev[x]) { swap(lc[x], rc[x]); if (lc[x]) rev[lc[x]] ^= 1; if (rc[x]) rev[rc[x]] ^= 1; rev[x] = 0; } } inline void Rotate(int x) { int y = fa[x], z = fa[y], b = lc[y] == x ? rc[x] : lc[x]; if (z && !isRoot(y)) (lc[z] == y ? lc[z] : rc[z]) = x; fa[x] = z; fa[y] = x; if (b) fa[b] = y; if (lc[y] == x) rc[x] = y, lc[y] = b; else lc[x] = y, rc[y] = b; Uptdate(y); } inline void Splay(int x) { que[qr = 1] = x; for (int y = x; !isRoot(y); y = fa[y]) que[++qr] = fa[y]; for (int i = qr; i; --i) pushDown(que[i]); while (!isRoot(x)) { if (!isRoot(fa[x])) Which(fa[x]) == Which(x) ? Rotate(fa[x]) : Rotate(x); Rotate(x); } Uptdate(x); } inline void Access(int x) { for (int y = 0; x; y = x, x = fa[x]) { Splay(x); rc[x] = y; if (y) fa[y] = x; Uptdate(x); } } inline int findRoot(int x) { Access(x); Splay(x); while (pushDown(x), lc[x]) x = lc[x]; Splay(x); return x; } inline void makeRoot(int x) { Access(x); Splay(x); rev[x] ^= 1; } inline void Link(int x, int y) { makeRoot(x); fa[x] = y; } inline void Cut(int x, int y) { makeRoot(x); Access(y); Splay(y); lc[y] = fa[x] = 0; Uptdate(y); } inline int Select(int x, int y) { makeRoot(x); Access(y); Splay(y); //把x置为根后,标记未下传,影响询问结果,因此Splay(y) return sze[y] - 1; } }; using namespace LCT; int main() { // freopen("bounce.in", "r", stdin); // freopen("bounce.out", "w", stdout); n = get() + 1; for (int i = 1; i <= n; ++i) sze[i] = 1; for (int i = 1; i < n; ++i) k[i] = get(), Link(i, Min(i + k[i], n)); m = get(); int x, y; while (m--) { x = get(); y = get() + 1; if (x & 1) put(Select(y, n)), outChar('\n'); else { Cut(y, Min(y + k[y], n)); k[y] = get(); Link(y, Min(y + k[y], n)); } } fwrite(fwt, 1, ohed - fwt, stdout); // fclose(stdin); fclose(stdout); return 0; }
相关文章推荐
- [题解]bzoj2002(HNOI2010)Bounce 弹飞绵羊
- bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【LCT】
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 分块
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块
- BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 LCT
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊 lct模板
- 【分块】BZOJ2002(Hnoi2010)[Bounce 弹飞绵羊]题解
- bzoj 2002 [Hnoi2010]Bounce 弹飞绵羊
- [bzoj2002][Hnoi2010]Bounce 弹飞绵羊【LCT】
- BZOJ2002[Hnoi2010][Bounce 弹飞绵羊]
- BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊
- bzoj2002:[Hnoi2010]Bounce 弹飞绵羊
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 分块/LCT
- BZOJ 2002[Hnoi2010]Bounce 弹飞绵羊
- 【LCT】BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊
- BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊