[BZOJ2002] [HNOI2010] 弹飞绵羊 - Link-Cut-Tree (LCT)
2016-06-07 16:25
429 查看
LCT绝对的模板题啊(黄学长一开始用分块写的感觉很高端啊%%%
呐……LCT写起来也是很简单的啊……根本不用维护一些其他的东西,只要最基本的操作。询问都不用别的直接makeroot然后access然后splay就好……
好吧具体看代码。建议在最后加一个点n+1(感觉不加我就不会写。
#include "algorithm"
#include "iostream"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "vector"
#include "math.h"
#include "map"
#include "set"
#define rep(f,a,b) for(f=a;f<=b;f++)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node {
node *fa,*c[2];
int size;
bool rev;
node ();
void push_up();
void push_down();
} Tnull,*null=&Tnull;
const int N=200005;
int n,a
,q; node v
;
node :: node(){
fa=c[0]=c[1]=null;
size=0; rev=false;
}
void node :: push_up(){
size=c[0]->size+c[1]->size+1;
}
void node :: push_down(){
if (fa->c[0]==this || fa->c[1]==this)
fa->push_down();
if(rev){
c[0]->rev^=1;
c[1]->rev^=1;
swap(c[0],c[1]);
rev=false;
}
}
inline bool isroot (node *x){
return x->fa->c[0]!=x && x->fa->c[1]!=x;
}
void rotate (node *x){
node *y=x->fa,*z=y->fa;
if (z!=null){
if(z->c[0]==y) z->c[0]=x;
if(z->c[1]==y) z->c[1]=x;
}
int l=y->c[1]==x,r=l^1;
if(x->c[r]!=null) x->c[r]->fa=y;
x->fa=z; y->fa=x; y->c[l]=x->c[r];
x->c[r]=y; y->push_up(); x->push_up();
}
void splay (node *x){
x->push_down();
while (isroot(x)^1){
node *y=x->fa,*z=y->fa;
if(isroot(y)^1){
if (z->c[0]==y ^ y->c[0]==x) rotate(x);
else rotate(y);
}
rotate(x);
}
x->push_up();
}
void access (node *x){
for (node *y=null;x!=null;y=x,x=x->fa)
splay(x),x->c[1]=y,x->push_up();
}
void makeroot (node *x){
access(x); splay(x);
x->rev^=1;
}
void link (node *x,node *y){
makeroot(x);
x->fa=y;
}
void cut (node *x,node *y){
makeroot(x); access(y);
splay(y); x->fa=null;
y->c[0]=null; y->push_up();
}
int work (node *x){
makeroot(v+n+1);
access(x); splay(x);
x->push_down();
return x->size-1;
}
int main(){
int i; n=read();
rep(i,1,n){ a[i]=read();
if(i+a[i]<=n)
link(v+i,v+i+a[i]);
else link(v+i,v+n+1);
} v[n+1].size=1;
int type,tot,pos; q=read();
rep(i,1,q){ type=read();
if(type==1){ pos=read(); pos++;
printf("%d\n",work(v+pos));}
else { pos=read(); tot=read(); pos++;
if(pos+a[pos]<=n)cut(v+pos,v+pos+a[pos]); else cut(v+pos,v+n+1);
if(pos+tot<=n)link(v+pos,v+pos+(a[pos]=tot));
else link(v+pos,v+n+1),a[pos]=tot;
}
}
return 0;
}
呐……LCT写起来也是很简单的啊……根本不用维护一些其他的东西,只要最基本的操作。询问都不用别的直接makeroot然后access然后splay就好……
好吧具体看代码。建议在最后加一个点n+1(感觉不加我就不会写。
#include "algorithm"
#include "iostream"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "vector"
#include "math.h"
#include "map"
#include "set"
#define rep(f,a,b) for(f=a;f<=b;f++)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node {
node *fa,*c[2];
int size;
bool rev;
node ();
void push_up();
void push_down();
} Tnull,*null=&Tnull;
const int N=200005;
int n,a
,q; node v
;
node :: node(){
fa=c[0]=c[1]=null;
size=0; rev=false;
}
void node :: push_up(){
size=c[0]->size+c[1]->size+1;
}
void node :: push_down(){
if (fa->c[0]==this || fa->c[1]==this)
fa->push_down();
if(rev){
c[0]->rev^=1;
c[1]->rev^=1;
swap(c[0],c[1]);
rev=false;
}
}
inline bool isroot (node *x){
return x->fa->c[0]!=x && x->fa->c[1]!=x;
}
void rotate (node *x){
node *y=x->fa,*z=y->fa;
if (z!=null){
if(z->c[0]==y) z->c[0]=x;
if(z->c[1]==y) z->c[1]=x;
}
int l=y->c[1]==x,r=l^1;
if(x->c[r]!=null) x->c[r]->fa=y;
x->fa=z; y->fa=x; y->c[l]=x->c[r];
x->c[r]=y; y->push_up(); x->push_up();
}
void splay (node *x){
x->push_down();
while (isroot(x)^1){
node *y=x->fa,*z=y->fa;
if(isroot(y)^1){
if (z->c[0]==y ^ y->c[0]==x) rotate(x);
else rotate(y);
}
rotate(x);
}
x->push_up();
}
void access (node *x){
for (node *y=null;x!=null;y=x,x=x->fa)
splay(x),x->c[1]=y,x->push_up();
}
void makeroot (node *x){
access(x); splay(x);
x->rev^=1;
}
void link (node *x,node *y){
makeroot(x);
x->fa=y;
}
void cut (node *x,node *y){
makeroot(x); access(y);
splay(y); x->fa=null;
y->c[0]=null; y->push_up();
}
int work (node *x){
makeroot(v+n+1);
access(x); splay(x);
x->push_down();
return x->size-1;
}
int main(){
int i; n=read();
rep(i,1,n){ a[i]=read();
if(i+a[i]<=n)
link(v+i,v+i+a[i]);
else link(v+i,v+n+1);
} v[n+1].size=1;
int type,tot,pos; q=read();
rep(i,1,q){ type=read();
if(type==1){ pos=read(); pos++;
printf("%d\n",work(v+pos));}
else { pos=read(); tot=read(); pos++;
if(pos+a[pos]<=n)cut(v+pos,v+pos+a[pos]); else cut(v+pos,v+n+1);
if(pos+tot<=n)link(v+pos,v+pos+(a[pos]=tot));
else link(v+pos,v+n+1),a[pos]=tot;
}
}
return 0;
}
相关文章推荐
- JAVA打包war的几种方法
- virtulenv说明
- 游戏设计中几种常用机器学习算法合集
- 在Python的Flask中使用WTForms表单框架的基础教程
- vim简单配置
- 单链表
- 谈谈MySQL的异常处理
- IOS 界面传值方法
- DSP的Baud Rate 、Baud Clock以及UART Input Clock之间的关系
- Burpsuite截断上传拿webshell
- dedecms 模板文件不存在,无法解析文档"的终极各种解决办法
- Java 类初始化顺序
- java中 用telnet 判断服务器远程端口是否开启
- ArcGIS Server开发实践之【Search Widget工具查询本地地图服务】
- CentOS安装rar及用法
- android出现注: 某些输入文件使用或覆盖了已过时的 API。 注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。 注: 某些输入文件使用了未经检查或不安全的操作。 注
- C++ 实现动态定义三维内的数组
- DELPHI 包装.NET COM组件
- Android学习之 WebView使用小结
- Android 沉浸式状态栏的实现方法、状态栏透明