非常简单的一眼LCT,然而我没有在20min内码完,太失败了...

第一问,直接查根的前驱

第二问,查链的子树大小

复杂度$O((n + m) log n)$

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; extern inline char gc() {
static char RR[], *S = RR + , *T = RR + ;
if(S == T) fread(RR, , , stdin), S = RR;
return *S ++;
}
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') p = p * + c - '', c = gc();
return p * w;
} int wr[], rw;
#define pc(o) *W ++ = (o)
char WR[], *W = WR;
inline void write(int x, char c) {
if(!x) pc('');
if(x < ) x = -x, pc('-');
while(x) wr[++ rw] = x % , x /= ;
while(rw) pc(wr[rw --] + ''); pc(c);
} #define ri register int
#define sid 200500 #define ls(o) s[o][0]
#define rs(o) s[o][1]
int n, m, a[sid];
int fa[sid], s[sid][], rev[sid], sz[sid]; inline bool isr(int o) { return ls(fa[o]) != o && rs(fa[o]) != o; }
inline bool isrc(int o) { return rs(fa[o]) == o; }
inline void upd(int o) { sz[o] = sz[ls(o)] + sz[rs(o)] + ; } inline void rotate(int o) {
int f = fa[o], g = fa[f];
int ro = isrc(o), rf = isrc(f);
fa[o] = g; if(!isr(f)) s[g][rf] = o;
if(s[o][ro ^ ]) fa[s[o][ro ^ ]] = f;
s[f][ro] = s[o][ro ^ ]; fa[f] = o; s[o][ro ^ ] = f;
upd(f); upd(o);
} inline void prev(int o) {
swap(ls(o), rs(o));
rev[o] ^= ;
} inline void prv(int o) {
if(!rev[o]) return;
prev(ls(o)); prev(rs(o)); rev[o] = ;
} inline void pushrev(int o) {
if(!isr(o)) pushrev(fa[o]);
prv(o);
} void splay(int o) {
pushrev(o);
while(!isr(o)) {
int f = fa[o];
if(!isr(f)) rotate(isrc(o) == isrc(f) ? f : o);
rotate(o);
}
} void access(int o) {
for(ri t = ; o; t = o, o = fa[o])
splay(o), s[o][] = t, upd(o);
} inline void makeroot(int o) {
access(o); splay(o); prev(o);
} inline void link(int u, int v) {
makeroot(u); fa[u] = v;
} inline void cut(int u, int v) {
makeroot(u); access(v); splay(v);
s[v][] = ; fa[u] = ; upd(v);
} inline int get(int u) {
prv(u); u = s[u][]; prv(u);
while(s[u][]) u = s[u][], prv(u);
return u;
} inline void qry(int u) {
makeroot(n + ); access(u); splay(n + );
int ans2 = sz[n + ] - , ans1 = get(n + );
splay(ans1); write(ans1, ' '); write(ans2, '\n');
} int main() {
n = read(); m = read();
for(ri i = ; i <= n; i ++) {
a[i] = read();
if(i + a[i] <= n) link(i, i + a[i]);
else link(i, n + );
}
for(ri i = ; i <= m; i ++) {
int opt = read(), x = read();
if(opt == ) {
if(x + a[x] <= n) cut(x, x + a[x]); else cut(x, n + ); int y = read();
a[x] = y; if(x + a[x] <= n) link(x, x + a[x]); else link(x, n + );
} else qry(x);
}
fwrite(WR, , W - WR, stdout);
return ;
}

最新文章

  1. Understanding Chan Chan&#39;s in Go
  2. Redis学习笔记~Redis并发锁机制
  3. Yii的学习(2)--数据访问对象 (DAO)
  4. RDIFramework.NET ━ 9.14 数据库连接管理 ━ Web部分
  5. 转载 - LINUX下查看CPU使用率的命令
  6. Android基于GridView实现的翻牌游戏效果
  7. 点击播放js
  8. iOS学习之下拉刷新
  9. mybatis 主键UUID生成策略
  10. 横截面数据分类——基于R
  11. 【ASP.NET Core分布式项目实战】(一)IdentityServer4登录中心、oauth密码模式identity server4实现
  12. 调用awk的三种方式
  13. react,react native,webpack,ES6,node.js----------今天上午学了一下node.js
  14. C语言--第1次作业
  15. linux alias 用法
  16. e充电加密破解
  17. UVA.12230.Crossing Rivers(期望)
  18. 如何在页面中获取到ModelAndView绑定的值
  19. Qt Widgets——子区域和子窗口
  20. (原+转)ubuntu中将文件夹打包成iso的命令

热门文章

  1. Vue笔记之props验证
  2. L - SOS Gym - 101775L 博弈
  3. uboot1.1.6 start.s分析
  4. PHP深浅拷贝
  5. python之微信公众号开发(基本配置和校验)
  6. 64_p5
  7. 生成器(generator)和迭代(iterable , iterator, iteration)
  8. C/C++——[05] 函数
  9. Condition接口
  10. csu 1549: Navigition Problem(几何,模拟)