这篇文章讲的很好很详细,但是写了几天后发现似乎是挺残的版本。

2049: [Sdoi2008]Cave 洞穴勘测

3282: Tree

2002: [Hnoi2010]Bounce 弹飞绵羊

1036: [ZJOI2008]树的统计Count

都是基础操作吧

后来发现makeroot这个操作可以用个各个地方,改进了一下愉快的切

2631: tree

结果就是tle

结果就是调了两天用了三种lct中splay写法还是tle

结果就是不明白某大神友情提供的代码到底比我的程序优在哪……!

至今还是tle,但是换了几种写法

写法一(自己的程序+各种奇怪的优化+网上大众版splay)

{$M 1000000000,0,maxlongint}

//{$ inline in}

type

  arr=record

    toward,next:longint;

  end;

const

  maxn=;

  mm=;

var

  a:array[..]of longint;

  st:string;

  fa,q,first,size:array[..maxn]of longint;

  sum,mark1,mark2,value:array[..maxn]of qword;

  c:array[..maxn,..]of longint;

  rev:array[..maxn]of boolean;

  edge:array[..maxn*]of arr;

  n,m,tot,u,v,j,k,i:longint;

procedure prepare;//inline;

  var

    i,j,k:longint;

  begin

    st:=st+' ';

    i:=;

    j:=;

    while i<length(st) do

      begin

      inc(j); k:=i;

      while st[i]<>' ' do inc(i);

      val(copy(st,k,i-k),a[j]);

      inc(i);

      end;

  end;

procedure swap(var x,y:longint);//inline;

var

  i:longint;

begin

  i:=x;

  x:=y;

  y:=i

end;

function isroot(x:longint):boolean;

begin

  if (c[fa[x],]=x) or (c[fa[x],]=x) then exit(True);

  exit(false);

end;       

procedure update(x:longint);//inline;

begin

  sum[x]:=(sum[c[x,]]+sum[c[x,]]+value[x]) mod mm;

  size[x]:=size[c[x,]]+size[c[x,]]+;

end;

procedure maintain(x,y,z:longint);//inline;

begin

  if x= then exit;

  value[x]:=(value[x]*y+z) mod mm;

  sum[x]:=(sum[x]*y+z*size[x])mod mm;

  mark1[x]:=mark1[x]*y mod mm;

  mark2[x]:=(mark2[x]*y+z) mod mm

end;

procedure pushdown(x:longint);//inline;

var

  l,r:longint;

begin

  if x= then exit;

  if rev[x] then begin

    swap(c[x,],c[x,]);

    rev[c[x,]]:=not rev[c[x,]];

    rev[c[x,]]:=not rev[c[x,]];

    rev[x]:=false;

  end;

  if (mark1[x]<>) or (mark2[x]<>) then begin

    maintain(c[x,],mark1[x],mark2[x]);

    maintain(c[x,],mark1[x],mark2[x]);

    mark1[x]:=;

    mark2[x]:=;

  end

end;

procedure rotate(x:longint);//inline;

var

  y,z,l,r:longint;

begin

  y:=fa[x];

  z:=fa[y];

  if c[y,]=x then l:= else l:=;

  r:=l xor ;

  if isroot(y) then

    if c[z,]=y then c[z,]:=x else c[z,]:=x;

  fa[x]:=z;

  fa[y]:=x;

  fa[c[x,r]]:=y;

  c[y,l]:=c[x,r];

  c[x,r]:=y;

  update(y);

  //update(x)

end;

procedure splay(x:longint);//inline;

var

  top,i,y,z:longint;

begin

  top:=;

  q[]:=x;

  i:=x;

  while isroot(i) do begin

    inc(top);

    q[top]:=fa[i];

    i:=fa[i];

  end;

  for i:=top downto  do pushdown(q[i]);

  while isroot(x) do begin

    y:=fa[x];

    z:=fa[y];

    if isroot(y) then

      if (c[y,]=x) xor (c[z,]=y) then rotate(x)

        else rotate(y);

    rotate(x);

  end

end;

function access(x:longint):longint;//inline;

var

  y:longint;

begin

  y:=;

  repeat

    splay(x);

    c[x,]:=y;

    fa[y]:=x;

    update(x);

    y:=x;

    x:=fa[x];

  until x=;

  exit(y);

end;

procedure makeroot(x:longint);//inline;

var

  y:longint;

begin

  y:=access(x);

  //splay(x);

  rev[y]:=not rev[y];

  fa[y]:=;

end;

procedure lct(x1,y1,x2,y2:longint);//inline;

var

  y:longint;

begin

  makeroot(x1);

  access(x1);

  y:=y1;

  while isroot(y) do y:=fa[y];

  fa[y]:=;

  y:=x2;

  while fa[y]<> do y:=fa[y];

  if y<>x1 then swap(x2,y2);

  y:=access(y2);

  rev[y]:=not rev[y];

  fa[y]:=x2

end;

procedure addedge(j,k:longint);//inline;

begin

  inc(tot);

  edge[tot].toward:=k;

  edge[tot].next:=first[j];

  first[j]:=tot

end;

procedure dfs(x:longint);//inline;

var

  i,too:longint;

begin

  i:=first[x];

  value[x]:=;

  sum[x]:=;

  mark1[x]:=;

  size[x]:=;

  while i<> do begin

    too:=edge[i].toward;

    if fa[x]<>too then begin

      fa[too]:=x;

      dfs(too);

    end;

    i:=edge[i].next;

  end

end;

begin

  readln(n,m);

  for i:= to n- do begin

    readln(j,k);

    addedge(j,k);

    addedge(k,j);

  end;

  dfs(n>>);

  while m> do begin

    dec(m);

    readln(st);

    prepare;

    case st[] of

      '*':begin

            //j:=j mod mm;

            makeroot(a[]);

            //maintain1(access(a[]),a[]);

            maintain(access(a[]),a[],);

      end;

      '+':begin

            //j:=j mod mm;

            makeroot(a[]);

            //maintain2(access(a[]),a[]);

            maintain(access(a[]),,a[]);

      end;

      '-':lct(a[],a[],a[],a[]);

      '/':begin

            makeroot(a[]);

            writeln(sum[access(a[])]);

      end;

    end;

  end;

end.

写法二(yangzhe大神写法)

type

  arr=record

    toward,next:longint;

  end;

const

  maxn=;

  mm=;

var

  a:array[..]of longint;

  st:string;

  fa,q,first,size,child:array[..maxn]of longint;

  sum,mark1,mark2,value:array[..maxn]of qword;

  c:array[..maxn,..]of longint;

  rev:array[..maxn]of boolean;

  edge:array[..maxn*]of arr;

  n,m,tot,u,v,j,k,i:longint;

procedure prepare;

  var

    i,j,k:longint;

  begin

    st:=st+' ';

    i:=;

    j:=;

    while i<length(st) do

      begin

      inc(j); k:=i;

      while st[i]<>' ' do inc(i);

      val(copy(st,k,i-k),a[j]);

      inc(i);

      end;

  end;

procedure swap(var x,y:longint);

var

  i:longint;

begin

  i:=x;

  x:=y;

  y:=i;

end;

procedure update(x:longint);

begin

  sum[x]:=(sum[c[x,]]+sum[c[x,]]+value[x]) mod mm;

  size[x]:=size[c[x,]]+size[c[x,]]+;

end;

procedure maintain(x,y,z:longint);

begin

  if x= then exit;

  value[x]:=(value[x]*y+z) mod mm;

  sum[x]:=(sum[x]*y+z*size[x])mod mm;

  mark1[x]:=mark1[x]*y mod mm;

  mark2[x]:=(mark2[x]*y+z) mod mm

end;

procedure pushdown(x:longint);

var

  l,r:longint;

begin

  if x= then exit;

  if rev[x] then begin

    child[c[x,]]:=-child[c[x,]];

    child[c[x,]]:=-child[c[x,]];

    swap(c[x,],c[x,]);

    rev[c[x,]]:=not rev[c[x,]];

    rev[c[x,]]:=not rev[c[x,]];

    rev[x]:=false;

  end;

  if (mark1[x]<>) or (mark2[x]<>) then begin

    maintain(c[x,],mark1[x],mark2[x]);

    maintain(c[x,],mark1[x],mark2[x]);

    mark1[x]:=;

    mark2[x]:=;

  end

end;

procedure rotate(node,x:longint);

var

  p,y,tmp:longint;

begin

  p:=fa[node];

  y:=child[p];

  tmp:=fa[p];

  fa[node]:=tmp;

  child[node]:=y;

  if y<> then c[tmp,y]:=node;

  y:=-x;

  tmp:=c[node,y];

  c[p,x]:=tmp;

  fa[tmp]:=p;

  child[tmp]:=x;

  fa[p]:=node;

  child[p]:=y;

  c[node,y]:=p;

  update(p);

end;

procedure splay(node:longint);

var

  a,p,b,top:longint;

begin

  top:=;

  q[]:=node;

  i:=node;

  while child[i]<> do begin

    inc(top);

    q[top]:=fa[i];

    i:=fa[i];

  end;

  for i:=top downto  do pushdown(q[i]);

  repeat

    a:=child[node];

    if a= then break;

    p:=fa[node];

    b:=child[p];

    if a=b then rotate(p,a)

           else rotate(node,a);

    if b= then break;

    rotate(node,b);

  until false;

  update(node);

end;

function access(x:longint):longint;

var

  y:longint;

begin

  y:=;

  repeat

    splay(x);

    child[c[x,]]:=;

    c[x,]:=y;

    fa[y]:=x;

    child[y]:=;

    update(x);

    y:=x;

    x:=fa[x];

  until x=;

  exit(y);

end;

procedure makeroot(x:longint);

var

  y:longint;

begin

  y:=access(x);

  rev[y]:=not rev[y];

  fa[y]:=;

  child[y]:=;

end;

function getrt(x:longint):longint;

begin

  while child[x]<> do x:=fa[x];

  exit(x);

end;

function getup(x:longint):longint;

begin

  while fa[x]<> do x:=fa[x];

  exit(x);

end;

procedure lct(x1,y1,x2,y2:longint);

var

  y:longint;

begin

  makeroot(y1);

  access(y1);

  y:=getrt(x1);

  fa[y]:=;

  child[y]:=;

  if getup(x2)<>x1 then swap(x2,y2);

  y:=access(y2);

  rev[y]:=not rev[y];

  fa[y]:=x2;

  child[y]:=;

end;

procedure addedge(j,k:longint);

begin

  inc(tot);

  edge[tot].toward:=k;

  edge[tot].next:=first[j];

  first[j]:=tot

end;

procedure dfs(x:longint);

var

  i,too:longint;

begin

  i:=first[x];

  value[x]:=;

  sum[x]:=;

  mark1[x]:=;

  size[x]:=;

  while i<> do begin

    too:=edge[i].toward;

    if fa[x]<>too then begin

      fa[too]:=x;

      child[too]:=;

      dfs(too);

    end;

    i:=edge[i].next;

  end

end;

begin

  readln(n,m);

  for i:= to n- do begin

  readln(j,k);

  addedge(j,k);

  addedge(k,j);

  end;

  child[n>>]:=;

  dfs(n>>);

  while m> do begin

    dec(m);

    readln(st);

    prepare;

    case st[] of

      '*':begin

            //j:=j mod mm;

            makeroot(a[]);

            //maintain1(access(a[]),a[]);

            maintain(access(a[]),a[],);

      end;

      '+':begin

            //j:=j mod mm;

            makeroot(a[]);

            //maintain2(access(a[]),a[]);

            maintain(access(a[]),,a[]);

      end;

      '-':lct(a[],a[],a[],a[]);

      '/':begin

            makeroot(a[]);

            writeln(sum[access(a[])]);

      end;

    end;

  end;

end.

【以前的空间】link cut tree的更多相关文章

  1. link cut tree 入门

    鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...

  2. Codeforces Round #339 (Div. 2) A. Link/Cut Tree 水题

    A. Link/Cut Tree 题目连接: http://www.codeforces.com/contest/614/problem/A Description Programmer Rostis ...

  3. Link/cut Tree

    Link/cut Tree 一棵link/cut tree是一种用以表示一个森林,一个有根树集合的数据结构.它提供以下操作: 向森林中加入一棵只有一个点的树. 将一个点及其子树从其所在的树上断开. 将 ...

  4. 洛谷P3690 Link Cut Tree (模板)

    Link Cut Tree 刚开始写了个指针版..调了一天然后放弃了.. 最后还是学了黄学长的板子!! #include <bits/stdc++.h> #define INF 0x3f3 ...

  5. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  6. bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门

    link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isro ...

  7. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  8. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  9. [CodeForces - 614A] A - Link/Cut Tree

    A - Link/Cut Tree Programmer Rostislav got seriously interested in the Link/Cut Tree data structure, ...

  10. Link Cut Tree 总结

    Link-Cut-Tree Tags:数据结构 ##更好阅读体验:https://www.zybuluo.com/xzyxzy/note/1027479 一.概述 \(LCT\),动态树的一种,又可以 ...

随机推荐

  1. 相机imu外参标定

    1. 第一步初始化imu外参(可以从参数文档中读取,也可以计算出),VINS中处理如下: # Extrinsic parameter between IMU and Camera. estimate_ ...

  2. 封装Excls数据导出功能 返回一个下载链接地址

    /// <summary> /// 获取本地存储地址 /// </summary> /// <param name="dt"></para ...

  3. spring源码-bean之初始化-1

    一.spring的IOC控制反转:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了松耦合.当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查 ...

  4. Python 获取windows管理员权限办法

    from __future__ import print_function import ctypes, sys, os def is_admin(): try: return ctypes.wind ...

  5. VIM第七版

    ZZ:退出并保存 e!:退回到上次保存时的样子 cw:修改单词(自动进入插入模式) cc:修改一整行的内容 cs:修改一个词(自动进入插入模式) .:可以重复上一个命令 J:将下一行内容合并到本行末尾 ...

  6. 使用分治法求X的N次方,时间效率为lgN

    最近在看MIT的算法公开课,讲到分治法的求X的N次方时,只提供了数学思想,于是自己把代码写了下,虽然很简单,还是想动手写一写. int powerN(int x,int n){ if(n==0){ r ...

  7. OSG的组成结构

    OSG的组成结构 核心结构 OSG的功能类采用“命名空间+类名称”的形式来命名.命名空间的命名方式为:第一个单词小写,后继单词的首字母大写,例如osg.osgUtil.osgViewer等:类的名称则 ...

  8. Android Test和Logcat

    一 测试相关概念 是否有源码 黑盒测试: 测试工具 白盒测试: 对所有的源码特别熟悉 对特定的代码进行测试 都是编程 时间 单元测试(程序员) 模块测试 集成测试 系统测试 回归测试(改bug) 压力 ...

  9. Python文件操作大全

    Python 编程文件操作大全   文件打开模式 打开模式 执行操作 'r' 以只读方式打开文件(默认) 'w' 以写入的方式打开文件,会覆盖已存在的文件 'x' 如果文件已经存在,使用此模式打开将引 ...

  10. servlet和Jsp的复习整理

    servlet 1.生命周期 a.构造方法.生成一个servlet b.init()方法.当开启服务器时,servlet第一次被装载,servlet引擎调用这个servlet的init()的方法,只调 ...