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

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. 关于 Windows 10 字体安装目录的问题

    不知从什么时候开始,本人台式机的Win10系统在安装字体的时候并不是安装到C:\Windows\Fonts目录中,而是安装到%USERPROFILE%\AppData\Local\Microsoft\ ...

  2. MySQL☞upper函数

    upper(列名/字符串):把小写字母改为大写字母 格式: select  upper(列名/字符串) from 表名 如下图:

  3. C#冒泡排序法及优化

    冒泡排序法及优化: static void Main(string[] args) { , , , , , }; ; //冒泡排序法 ; i < sums.Length - ; i++) //总 ...

  4. [Clr via C#读书笔记]Cp1CLR执行模型

    Cp1CLR执行模型 本章的概念点 CLR=Common Language Runtime 内存管理,程序集加载,安全性,异常处理和线程同步.CLR是基础,支持着面向它的各种语言.各种语言会被对应的编 ...

  5. TensorFlow入门之MNIST最佳实践-深度学习

    在上一篇<TensorFlow入门之MNIST样例代码分析>中,我们讲解了如果来用一个三层全连接网络实现手写数字识别.但是在实际运用中我们需要更有效率,更加灵活的代码.在TensorFlo ...

  6. ThinkPHP - 5 - 学习笔记(2015.4.15)

    ThinkPHP __construct()和__initialize() 1.__initialize()不是php类中的函数,php类的构造函数只有__construct().2.类的初始化:子类 ...

  7. Python3 数据类型-元组

    Python 的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. 实例1(Python3.0+): tu ...

  8. 4-2:实现cp命令

    #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h& ...

  9. java线程一之创建线程、线程池以及多线程运行时间统计

    线程和进程的基本概念 进程和线程是动态的概念.         进程是 "执行中的程序",是一个动词,而程序是一个名词,进程运行中程序的"代码",而且还有自己的 ...

  10. Android - 时间 日期相关组件

    源码下载地址 : -- CSDN :  http://download.csdn.net/detail/han1202012/6856737 -- GitHub : https://github.co ...