From eca211499ac69e016651c1aa07251f6f3261700c Mon Sep 17 00:00:00 2001 From: Lee <501648152@qq.com> Date: Fri, 1 Sep 2017 09:26:16 +0800 Subject: [PATCH] New File:Algorithm.md --- Algorithm.md | 2178 +++++++++++++++++++++++++++++++++++++++++ assets/algorithm1.gif | Bin 0 -> 57313 bytes 2 files changed, 2178 insertions(+) create mode 100644 Algorithm.md create mode 100644 assets/algorithm1.gif diff --git a/Algorithm.md b/Algorithm.md new file mode 100644 index 0000000..4a5a11e --- /dev/null +++ b/Algorithm.md @@ -0,0 +1,2178 @@ +# 数据结构和算法 + +该文章来自[我](https://www.github.com/lisongting) 的[https://github.com/lisongting/preparation](https://github.com/lisongting/preparation) ,这个preparation是我整理的一些面试知识点,其中有些内容和图片是来自知名博客,有些内容是我自己总结的。我打算逐渐将preparation中的内容推到[该项目](https://github.com/lisongting/android-interview-questions-cn)中,供更多人学习参考。欢迎提Issue和Pull Request. + +进入主题,该文档包含了以下算法的Java实现: + +

目录

+ +* [1.表](#1) + * [1.1顺序表](#1.1) + * [1.2单链表](#1.2) + * [1.3双链表](#1.3) +* [2.栈和队列](#2) + * [2.1顺序栈](#2.1) + * [2.2链式栈](#2.2) + * [2.3循环队列](#2.3) +* [3.树](#3) + * [3.1普通二叉树](#3.1) + * [3.2二叉搜索树](#3.2) +* [4.排序](#4) + * [4.1冒泡排序](#4.1) + * [4.2快速排序](#4.2) + * [4.3直接选择排序](#4.3) + * [4.4堆排序](#4.4) + * [4.5直接插入排序](#4.5) + * [4.6折半插入排序](#4.6) + * [4.7希尔排序](#4.7) + * [4.8归并排序](#4.8) + * [4.9基数排序](#4.9) + * [4.10复杂度比较](#4.10) +* [5.查找](#5) + * [5.1朴素查找](#5.1) + * [5.2KMP](#5.2) + +

1.表

+ +

1.1顺序表

+ +```java +import java.util.Arrays; + +public class SequenceList { + private int DEFAULT_SIZE = 16; + private int capacity; + private Object[] elementData; + private int size = 0; + public SequenceList(){ + capacity = DEFAULT_SIZE; + elementData = new Object[capacity]; + } + public SequenceList(T element){ + this(); + elementData[0] = element; + size ++; + } + //初始化第一个元素,以指定大小创建List + public SequenceList(T element,int initSize){ + capacity = 1; + //把capacity设为大于initSize的数,并且为2的n次方 + while(capacity < initSize){ + capacity = capacity * 2; + } + elementData = new Object[capacity]; + elementData[0] = element; + size++; + } + public int length(){ + return size; + } + public T get(int index){ + if(index<0||index>size-1){ + throw new IndexOutOfBoundsException("线性表索引越界"); + } + return (T) elementData[index]; + } + public int locate(T element){ + for(int i=0;i size){ + throw new IndexOutOfBoundsException("线性表索引越界"); + } + + ensureCapacity(size+1); + size ++; + //把index位置以后的元素都向后移 + for(int i=size-1;i>index;i--){ + elementData[i] = elementData[i-1]; + } + elementData[index] = element; + } + + //删除指定下标位置的元素 + public void delete(int index){ + if(index < 0 ||index> size-1){ + throw new IndexOutOfBoundsException("线性表索引越界"); + } + //把从指定位置的元素都往前移动 + for(int i = index;i capacity){ + capacity *= 2; + } + elementData = Arrays.copyOf(elementData, capacity); + } + public static void main(String[] args){ + SequenceList list = new SequenceList<>(); + list.add("aaaa"); + list.add("bbbb"); + list.add("cccc"); + System.out.println(list.get(2)); + System.out.println(list.toString()); + list.insert(1, "tttt"); + System.out.println(list.toString()); + list.delete(0); + System.out.println(list.toString()); + System.out.println("tttt在线性表中的位置是:"+list.locate("tttt")); + } +} +``` +[回到目录](#index) + +

1.2单链表

+ +```java +public class LinkList { + //定义一个内部类 + private class Node{ + private T data; + private Node next; + public Node(){}; + public Node(T data,Node next){ + this.data = data; + this.next = next; + } + } + private Node header; + private Node tail; + private int size = 0; + public LinkList(){ + //空链表 + header = tail = null; + } + public LinkList(T element){ + header = new Node(element,null); + tail = header; + size++; + } + public int length(){ + return size; + } + //根据索引查找指定位置的节点 + public Node getNodeByIndex(int index){ + if(index < 0||index >size-1){ + throw new IndexOutOfBoundsException("链表索引越界"); + } + Node current = header; + for(int i=0;i < size && current!=null;i++){ + if(i == index){ + return current; + } + current = current.next; + } + return null; + } + //根据节点返回所在的位置 + public int locate(T element){ + Node current = header; + for(int i=0;isize){ + throw new IndexOutOfBoundsException("链表索引越界"); + } + if(header == null){ + add(element); + }else{ + if(index==0){ + addAtHeader(element); + }else{ + //获取插入节点的前一个节点 + Node prev = getNodeByIndex(index -1); + //prev的next指向新节点 + //让新节点的next指向原来prev的下一个节点 + prev.next = new Node(element,prev.next); + size++; + } + } + + } + public void add(T element){ + if(header == null){ + header = new Node(element,null); + tail = header; + }else{ + Node newNode = new Node(element,null); + tail.next = newNode; + tail = newNode; + } + size ++; + } + public void addAtHeader(T element){ + Node tmp = new Node(element,header); + header = tmp; + //如果在插入之前是空链表 + if(tail == null){ + tail = header; + } + size ++; + } + //[重要]删除指定索引处的元素 + public void delete(int index){ + if(index < 0 || index>size-1){ + throw new IndexOutOfBoundsException("链表索引越界"); + } + Node del = null; + //如果被删除的是头节点 + if(index ==0){ + header = null; + header = header.next; + }else{ + //获取删除节点的前一个节点 + Node prev = getNodeByIndex(index-1); + //获取将要被删除的节点 + del = prev.next; + prev.next = del.next; + del = null; + } + size --; + } + public void remove(){ + delete(size -1); + } + public boolean isEmpty(){ + return size ==0; + } + public void clear(){ + Node current = header; + for(int i=0;i list = new LinkList<>(); + list.insert(0, "aaaa"); + list.add("bbbb"); + list.add("wwww"); + System.out.println(list.toString()); + list.addAtHeader("cccc"); + System.out.println(list.toString()); + System.out.println("1号位置是"+list.getNodeByIndex(1).data); + list.delete(1); + System.out.println(list.toString()); + System.out.println("wwww在链表中的位置是:"+list.locate("wwww")); + + } + +} + +``` +[回到目录](#index) + + +

1.3双链表

+ +```java +package list; + + +//双链表 +public class DoubleLinkList { + + private class Node{ + private T data; + private Node prev; + private Node next; + public Node(){}; + public Node(T data,Node prev,Node next){ + this.data = data; + this.prev = prev; + this.next = next; + } + } + private Node header; + private Node tail; + private int size = 0; + public DoubleLinkList(){ + header = tail = null; + } + public DoubleLinkList(T element){ + header = new Node(element,null,null); + tail = header; + size ++; + } + public int length(){ + return size; + } + public boolean isEmpty(){ + return 0 == size; + } + //获取下标为index的节点的值 + public T get(int index){ + return getNodeByIndex(index).data; + } + //根据索引查找节点 + public Node getNodeByIndex(int index){ + if(index < 0 || index > size-1){ + throw new IndexOutOfBoundsException("链表索引越界"); + } + if(index <= size/2){ + Node current = header; + for(int i=0;i<=size/2 && current != null;i++){ + if(i == index){ + return current; + } + current = current.next; + } + }else{ + Node current = tail; + for(int i=size -1;i>size/2&¤t!=null ;i++){ + if(i == index){ + return current; + } + current = current.prev; + } + } + return null; + } + + //根据值查找索引值 + public int locate(T element){ + Node current = header; + for(int i=0;i size-1){ + throw new IndexOutOfBoundsException("链表索引越界"); + } + if(header == null){ + add(element); + }else{ + if(index ==0){ + addAtHeader(element); + }else{ + //获取插入点的前一个节点 + Node prev = getNodeByIndex(index-1); + //获取当前index处的节点 + Node next = prev.next; + Node newNode = new Node(element,prev,next); + prev.next = newNode; + next.prev = newNode; + size++; + } + } + + } + //在末尾插入元素 + public void add(T element){ + if(header ==null){ + header = new Node(element,null,null); + tail = header; + }else{ + Node newNode = new Node(element,tail,null); + tail.next = newNode; + tail = newNode; + } + size ++; + } + public void addAtHeader(T element){ + Node newNode = new Node(element,null,header); + header = newNode; + //如果插入之前是空链表 + if(tail == null){ + tail = header; + } + size++; + } + //[重要]删除指定索引处的节点 + public void delete(int index){ + if(index < 0 || index > size-1){ + throw new IndexOutOfBoundsException("链表索引越界"); + } + //如果要删除的是头节点 + if(index == 0){ + header = header.next; + header.prev = null; + }else if(index == size -1){//如果要删除尾节点 + Node prevNode = tail.prev; + tail = null; + prevNode.next=null; + tail = prevNode; + }else{ + //找到index位置之前的节点 + Node prevNode = getNodeByIndex(index-1); + Node delNode = prevNode.next; + Node nextNode = delNode.next; + delNode =null; + prevNode.next = nextNode; + nextNode.prev = prevNode; + } + size --; + } + //删除最后一个节点 + public void remove(){ + delete(size-1); + } + public void clear(){ + Node current = header; + for(int i=0;i list = new DoubleLinkList<>(); + list.add("aaa"); + list.add("bbb"); + list.insert("www", 1); + System.out.println(list.toString()); + list.addAtHeader("ccc"); + System.out.println(list.toString()); + System.out.println("1号位置的元素是"+list.get(1)); + list.delete(2); + System.out.println("调用delete(2)之后的链表:"+list.toString()); + list.remove(); + System.out.println("调用remove()之后的链表:"+list.toString()); + list.add("ttt"); + System.out.println("插入ttt之后"+list.toString()); + System.out.println("ttt存放的索引值是:"+list.locate("ttt")); + list.clear(); + System.out.println("清空链表之后 ,再次打印:"+list.toString()); + } + +} +``` +[回到目录](#index) + +

2.栈和队列

+ +

2.1顺序栈

+ +```java +import java.util.Arrays; + +public class SequenceStack { + private int DEFAULT_SIZE = 10; + private int capacity; + //程序每次增加的数组长度 + private int capacityIncrement = 0; + private Object[] elementData; + private int size = 0; + public SequenceStack(){ + capacity = DEFAULT_SIZE; + elementData = new Object[capacity]; + }; + //以第一个初始元素来构造顺序栈 + public SequenceStack(T element){ + this(); + elementData[0] = element; + size ++; + } + public SequenceStack(T element,int initSize){ + this.capacity = initSize; + elementData = new Object[capacity]; + elementData[0] = element; + size ++; + } + //以指定数组长度以及增量来创建顺序栈 + public SequenceStack(T element,int initSize, int increment){ + this.capacity = initSize; + this.capacityIncrement = increment; + elementData = new Object[capacity]; + elementData[0] = element; + size++; + } + public int length(){ + return size; + } + public boolean isEmpty(){ + return 0 == size; + } + //[重要]入栈 + public void push(T element){ + ensureCapacity(size+1); + elementData[size] = element; + size++; + } + //确保容量 + public void ensureCapacity(int needCapacity){ + if(needCapacity > capacity){ + if(capacityIncrement > 0){ + while(needCapacity > capacity){ + capacity += capacityIncrement; + } + }else{ + while(needCapacity > capacity){ + capacity *= 2; + } + } + } + elementData = Arrays.copyOf(elementData, capacity); + } + //入栈 + public T pop(){ + T tmp = (T) elementData[size-1]; + elementData[size - 1] =null; + size--; + return tmp; + } + //返回栈顶元素,但不删除 + public T peek(){ + return (T) elementData[size-1]; + } + public void clear(){ + for(int i=0;i stack = new SequenceStack<>(); + stack.push("aaaa"); + stack.push("bbbb"); + System.out.println("此时栈顶元素是:"+stack.peek()); + stack.push("cccc"); + System.out.println("自底向上栈内的元素为:"+stack.toString()); + stack.pop(); + System.out.println("出栈后栈内的元素为:"+stack.toString()); + stack.push("eeee"); + stack.push("tttt"); + System.out.println("自底向上栈内的元素为:"+stack.toString()); + stack.clear(); + System.out.println("清空后栈内的元素为:"+stack.toString()); + } +} + +``` +[回到目录](#index) + +

2.2链式栈

+ +```java +public class LinkStack { + private class Node{ + private T data; + private Node next;//该next是往栈底指 + public Node(){}; + public Node(T element){ + data = element; + } + public Node(T data,Node next){ + this.data = data; + this.next = next; + } + } + //栈顶元素 + private Node top; + private int size = 0; + public LinkStack(){ + top = null; + }; + public LinkStack(T element){ + top = new Node(element,null); + size ++; + } + public int length(){ + return size; + } + public boolean isEmpty(){ + return size == 0; + } + //[重要] + public void push(T element){ + Node newNode = new Node(element,top); + top = newNode; + size ++; + } + public T pop(){ + Node oldTop = top; + top = null; + top = oldTop.next; + size --; + return oldTop.data; + } + public T peek(){ + return top.data; + } + public void clear(){ + Node current = top; + for(int i=0;i stack = new LinkStack<>(); + stack.push("aaaa"); + stack.push("bbbb"); + System.out.println("此时栈顶元素是:"+stack.peek()); + stack.push("cccc"); + System.out.println("自顶向下栈内的元素为:"+stack.toString()); + stack.pop(); + System.out.println("出栈后栈内的元素为:"+stack.toString()); + stack.push("eeee"); + stack.push("tttt"); + System.out.println("自顶向下栈内的元素为:"+stack.toString()); + stack.clear(); + System.out.println("清空后栈内的元素为:"+stack.toString()); + } + +} + +``` +[回到目录](#index) + +

2.3循环队列

+ +```java +package queue; +//循环队列 +public class LoopQueue { + private int DEFAULT_SIZE = 10; + private int capacity; + private Object[] elementData; + //保存顺序队列中元素的当前个数 + private int front = 0; + private int rear = 0; + public LoopQueue(){ + capacity = DEFAULT_SIZE; + elementData = new Object[capacity]; + } + public LoopQueue(T element){ + this(); + elementData = new Object[capacity]; + rear++; + } + public LoopQueue(T element, int initSize){ + this.capacity = initSize; + elementData = new Object[capacity]; + elementData[0] = element; + rear ++; + } + public void add(T element){ + if(rear == front && elementData[front]!=null){ + throw new IndexOutOfBoundsException("队列已满"); + } + elementData[rear] = element; + rear++; + //如果rear已经到最大了,则掉头 + rear = rear==capacity? 0:rear; + } + //出队列 + public T remove(){ + if(isEmpty()){ + throw new IndexOutOfBoundsException("队列已满"); + } + T oldValue = (T)elementData[front]; + elementData[front] = null; + front++; + //如果front到头则掉头 + front = front==capacity? 0:front; + return oldValue; + } + //获取队列首部元素,不删除 + public T element(){ + if(isEmpty()){ + throw new IndexOutOfBoundsException("队列已满"); + } + return (T)elementData[front]; + } + public int length(){ + if(isEmpty()){ + return 0; + } + return rear > front ? rear - front :capacity-(front-rear); + } + public boolean isEmpty(){ + return rear == front && elementData[rear]==null; + } + public void clear(){ + for(int i=0;i=rear,那么有效元素为front~capacity和0到rear之间的 + for(int i=front;i queue = new LoopQueue<>(); + queue.add("aaaa"); + queue.add("bbbb"); + queue.add("cccc"); + queue.add("dddd"); + System.out.println(queue); + System.out.println("排在队首的元素是:"+queue.element()); + queue.remove(); + System.out.println("出队列之后:"+queue); + queue.add("wwww"); + System.out.println("插入wwww之后:"+queue); + queue.clear(); + System.out.println("清空队列后:"+queue); + + } + +} + +``` +[回到目录](#index) + +

3.树

+ +

3.1普通二叉树

+ +```java +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +//二叉链表树 +public class BinaryTree { + class Node{ + T data; + Node left; + Node right; + public Node(){}; + public Node(T data){ + this.data = data; + } + public Node(T data, Node left, Node right){ + this.data = data; + this.left = left; + this.right = right; + } + } + + private Node root; + public BinaryTree(){ + root = new Node(); + } + public BinaryTree(T data){ + root = new Node(data,null,null); + } + //为指定节点添加子节点 + public Node addNode(Node parent,T data,boolean isLeft){ + if(parent == null){ + throw new RuntimeException("parent节点为null,无法添加子节点"); + } + if(isLeft && parent.left!=null){ + throw new RuntimeException("parent已有左子节点,无法添加子节点"); + } + if(!isLeft && parent.right!=null){ + throw new RuntimeException("parent已有右子节点,无法添加子节点"); + } + Node newNode = new Node(data); + if(isLeft){ + parent.left = newNode; + }else{ + parent.right = newNode; + } + return newNode; + } + + public boolean isEmpty(){ + return root.data == null; + } + //获取根节点 + public Node root(){ + if(isEmpty()){ + throw new RuntimeException("树为空"); + } + return root; + } + //[重要]获取树的深度 + public int deep(Node root){ + if(root == null){ + return 0; + }else{ + return 1+Math.max(deep(root.left),deep(root.right)); + } + } + + //[重要]先序遍历:先遍历根节点 + //中序遍历和后序遍历都是同理 + public void preVisit(){ + List list = new ArrayList<>(); + list = preVisit(root); + for(int i=0;i preVisit(Node node){ + List tmpList = new ArrayList<>(); + //如果是中序遍历则将这行放在中间,如果是后序遍历则放在最后 + tmpList.add(node); + //递归处理左子树 + if(node.left != null){ + tmpList.addAll(preVisit(node.left)); + } + if(node.right != null){ + tmpList.addAll(preVisit(node.right)); + } + return tmpList; + } + + //[重要]广度优先遍历 + public void breadthFirst(){ + Queue queue = new ArrayDeque(); + List list = new ArrayList<>(); + if(root != null){ + queue.offer(root); + } + while(!queue.isEmpty()){ + //将根元素加入队列 + list.add(queue.peek()); + //从队列头部取出元素 + Node p = queue.poll(); + //如果左子节点不为空,则加入到队列 + if(p.left!=null){ + queue.offer(p.left); + } + if(p.right!=null){ + queue.offer(p.right); + } + } + //输出所有节点信息 + for(int i=0;i tree = new BinaryTree<>("A"); + BinaryTree.Node tn1 = tree.addNode(tree.root(), "B", true); + BinaryTree.Node tn2 = tree.addNode(tree.root(), "C", false); + BinaryTree.Node tn3 = tree.addNode(tn2, "D", true); + BinaryTree.Node tn4 = tree.addNode(tn2, "E", false); + BinaryTree.Node tn5 = tree.addNode(tn3, "F", true); + System.out.println("C的左子节点:"+tn2.left.data); + System.out.println("C的右子节点:"+tn2.right.data); + System.out.println("D的左子节点: "+tn3.left.data); + System.out.println("深度:"+tree.deep(tree.root())); + + System.out.print("先序遍历:"); + tree.preVisit(); + System.out.println(); + + System.out.print("广度优先遍历:"); + tree.breadthFirst(); + System.out.println(); + } + +} +/** + * 输出结果: + C的左子节点:D + C的右子节点:E + D的左子节点: F + 深度:4 + 先序遍历:A B C D F E + 广度优先遍历:A B C D E F +*/ + +``` +[回到目录](#index) + +

3.2二叉搜索树

+ +二叉排序树,也叫二叉搜索树,该代码构建的二叉搜索树节点存放整数。(也可以构造其他类型的二叉树,存放其他对象,只要能进行某种性质上的大小比较)根据整数大小来存放,比父节点小的总是为父节点左子节点。比父节点大的总是为父节点的右子节点。 + +```java +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +public class BinarySearchTree { + private class Node{ + int data; + Node left; + Node right; + public Node(){}; + public Node(int element){ + this.data = element; + left = right = null; + } + public Node(int element,Node left,Node right){ + this(element); + this.left = left; + this.right = right; + } + } + private Node root; + public BinarySearchTree(){ + root = null; + }; + //以根节点创建二叉搜索树 + public BinarySearchTree(int element){ + root = new Node(element); + } + //[重要]插入操作 + public void insert(int element){ + if(root == null){ + root = new Node(element); + }else{ + Node current = root; + Node parent = null; + Node newNode = new Node(element,null,null); + //该变量标记新节点在左还是在右 + boolean isLeft = false; + //寻找一个合适的位置作为插入点 + while(current != null){ + parent = current; + //如果新插入的节点大于当前的节点 + if(element > current.data){ + //则把当前节点右移 + current = current.right; + isLeft = false; + }else{ + //如果新节点小于等于当前节点,则把当前节点左移 + current = current.left; + isLeft = true; + } + } + //如果是在左,则新节点放到最后一次parent的左边 + if(isLeft){ + parent.left = newNode; + }else{ + parent.right = newNode; + } + } + } + //[重要]删除操作 + public void remove(int element){ + Node delNode = findNode(element);//先找到要删除的节点 + if(delNode == null){ + return; + } + //然后进行树结构调整操作 + //如果要删除的节点没有左右子节点,即它本身就是叶子节点 + if(delNode.left == null && delNode.right==null){ + //找到父节点 + Node parent = findParent(delNode); + //如果要删除的节点是左子节点 + if(delNode == parent.left){ + parent.left = null; + //这里手动将delNode设为null,如果不置为null起始也没关系 + //反正遍历树已经访问不到它了(估计它应该会被GC回收吧) + delNode = null; + } + if(delNode == parent.right){ + parent.right = null; + delNode = null; + } + } + //如果要删除的节点只有左子节点 + else if(delNode.left!=null && delNode.right==null){ + if(root == delNode){ + root = root.left; + }else{ + Node parent = findParent(delNode); + if(delNode == parent.left){ + parent.left = delNode.left; + }else if(delNode == parent.right){ + parent.right = delNode.left; + } + } + + } + //如果要删除的节点只有右子节点 + else if(delNode.left==null && delNode.right!=null){ + if(delNode == root){ + root = root.right; + }else{ + Node parent = findParent(delNode); + if(delNode == parent.left){ + parent.left = delNode.right; + }else if(delNode == parent.right){ + parent.right = delNode.right; + } + } + } + //如果要删除的节点有左右子节点 + else{ + //首先在其左子树中找到最大的那个值 + Node leftMaxNode = delNode.left; + while(leftMaxNode.right!=null ){ + leftMaxNode = leftMaxNode.right; + } + //找到leftMaxNode的父节点 + Node maxParent = findParent(leftMaxNode); + //找到delNode的父节点 + Node delNodeParent = findParent(delNode); + //这种情况容易忽略,如果leftMaxNode的父节点刚好是要删除的节点 + if(delNode == maxParent){ + if(delNodeParent.left == delNode){ + delNodeParent.left = leftMaxNode; + }else{ + delNodeParent.right = leftMaxNode; + } + leftMaxNode.right = delNode.right; + delNode = null; + }else{ + //由于leftMaxNode不可能是parent的左孩子, + //只可能是parent的右孩子 + //而leftMaxNode一定没有右孩子 + //所以将parentde右子节点指向leftMaxNode的左边(可能为null,也没关系) + //parent.right = null; + maxParent.right = leftMaxNode.left; + leftMaxNode.left = delNode.left; + leftMaxNode.right = delNode.right; + + //下面还要在delNodeParent中对delNode的位置进行替换 + //(孩子丢了,给老人家一个交代吧) + //如果delNode本来就是root节点 + if(delNodeParent == null){ + root = leftMaxNode; + }//如果delNode不是root节点 + else{ + if(delNode == delNodeParent.left){ + //给老人家一个新儿子 + delNodeParent.left = leftMaxNode; + }else{ + delNodeParent.right = leftMaxNode; + } + } + delNode.left = null; + delNode.right = null; + delNode = null; + } + } + } + //根据数字查找节点 + public Node findNode(int element){ + if(root == null){ + return null; + } + Node p = root; + while(p!=null){ + if(element > p.data){ + p = p.right; + }else if(element < p.data){ + p = p.left; + }else{ + return p; + } + } + return null; + } + //找到一个节点的父节点 + public Node findParent(Node child){ + if(child == null){ + return null; + } + if(child == root){ + return null; + } + Node current = root; + Node prev = current; + while(current!= null){ + if(current.data < child.data){ + prev = current; + current = current.right; + }else if(current.data > child.data){ + prev = current; + current = current.left; + }else{ + + return prev; + } + } + return null; + } + //[重要]中序遍历:先遍历左子节点 + public void middleVisit(){ + List list = new ArrayList<>(); + list = middleVisit(root); + for(int i=0;i middleVisit(Node node){ + List tmpList = new ArrayList<>(); + //递归处理左子树 + if(node.left != null){ + tmpList.addAll(middleVisit(node.left)); + } + tmpList.add(node); + if(node.right != null){ + tmpList.addAll(middleVisit(node.right)); + } + return tmpList; + } + //[重要]广度优先遍历 + public void breadthFirst(){ + Queue queue = new ArrayDeque(); + List list = new ArrayList<>(); + if(root != null){ + queue.offer(root); + } + while(!queue.isEmpty()){ + //将根元素加入队列 + list.add(queue.peek()); + //从队列头部取出元素 + Node p = queue.poll(); + //如果左子节点不为空,则加入到队列 + if(p.left!=null){ + queue.offer(p.left); + } + if(p.right!=null){ + queue.offer(p.right); + } + } + //输出所有节点信息 + for(int i=0;i4.排序 + +

4.1冒泡排序

+ + **冒泡排序** + + * (属于交换排序) + * 时间复杂度:O(n*n) + * 空间复杂度:O(1) + * 稳定性:稳定 + * 分析:最慢,效率最低的排序算法 + + + +```java +import java.util.Arrays; + +public class BubbleSort { + public static void bubbleSort(int[] array){ + System.out.println("开始排序:"); + for(int i=0;i array[j+1]){ + int tmp = array[j]; + array[j] = array[j+1]; + array[j+1] = tmp; + flag = true; + } + } + System.out.println(Arrays.toString(array)); + //如果某一趟中元素没有交换,则说明数组已经有序 + //为提高效率,则直接退出 + if(!flag){ + break; + } + } + } + public static void main(String[] args) { + int[] array = new int[]{5,10,3,29,12,52,36,25}; + System.out.println("排序前:"); + System.out.println(Arrays.toString(array)); + BubbleSort.bubbleSort(array); + System.out.println("排序后:"); + System.out.println(Arrays.toString(array)); + } + /**[运行结果] + * 排序前: + * [5, 10, 3, 29, 12, 52, 36, 25] + * 开始排序: + * [5, 3, 10, 12, 29, 36, 25, 52] + * [3, 5, 10, 12, 29, 25, 36, 52] + * [3, 5, 10, 12, 25, 29, 36, 52] + * [3, 5, 10, 12, 25, 29, 36, 52] + * 排序后: + * [3, 5, 10, 12, 25, 29, 36, 52] + */ +} +``` + + + + + +[回到目录](#index) + + + +

4.2快速排序

+ + **快速排序** + + * (属于交换排序) + * 时间复杂度:最好O(nlogn) 最坏O(n*n) + * 空间复杂度:O(logn) + * 稳定性:不稳定 + * 分析:快速排序比大部分排序算法都要快。 + * 快速排序思路:从待排序的数据序列中任意去一个数据作为分界,所有比它小的数据元素一律放在左边,所有比它大的元素一律放在右边,这样一趟下来,形成左右两个子序列,再对这两个子序列进行相同的处理,即重新选取中心元素。进行递归处理 + +```java +import java.util.Arrays; + +public class QuickSort { + public static void quickSort(int[] array,int start,int end){ + //需要排序 + if(start < end){ + //以第一个元素作为分界值 + int pivot = array[start]; + //i从左边开始搜索,查找大于分界值的元素索引 + int i = start; + //j从右边开始搜索,查找小于分界值的元素索引 + int j = end; + while(true){ + while(array[j]>=pivot && i4.3直接选择排序 + + * 直接选择排序 + * (属于选择排序) + * 时间复杂度:O(n*n) + * 空间复杂度:O(1) + * 稳定性:不稳定 + * 分析:和冒泡排序一样效率较低 + * 思路:第一趟从所有数据中选出最小的,放在第一位。第二趟从其他未排序位置中选出最小的,放在第二位,依次类推,一共需要进行n-1趟才能排好。 + +```java +import java.util.Arrays; + +public class SelectSort { + public static void selectSort(int[] array){ + //进行n-1趟比较,第i趟比较将第i大的值选出来放在i位置上 + for(int i=0;iarray[j]){ + int tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; + } + } + System.out.println(Arrays.toString(array)); + } + } + public static void main(String[] args) { + int[] array = new int[]{9,5,23,2,0,21,30,13}; + System.out.println("排序前:\n"+Arrays.toString(array)); + System.out.println("开始排序:"); + SelectSort.selectSort(array); + System.out.println("排序后:\n"+Arrays.toString(array)); + } + /*[运行结果] + 排序前: + [9, 5, 23, 2, 0, 21, 30, 13] + 开始排序: + [0, 9, 23, 5, 2, 21, 30, 13] + [0, 2, 23, 9, 5, 21, 30, 13] + [0, 2, 5, 23, 9, 21, 30, 13] + [0, 2, 5, 9, 23, 21, 30, 13] + [0, 2, 5, 9, 13, 23, 30, 21] + [0, 2, 5, 9, 13, 21, 30, 23] + [0, 2, 5, 9, 13, 21, 23, 30] + 排序后: + [0, 2, 5, 9, 13, 21, 23, 30] + */ +} +``` +[回到目录](#index) + + + +

4.4堆排序

+ **堆排序** + + * (属于选择排序) + * 时间复杂度:O(nlogn) + * 空间复杂度:O(1) + * 稳定性:不稳定 + * 分析:通过 重建堆,从根结点开始进行从上向下的调整。每次调整都将未排序区中最大的元素放在堆顶,然后将堆顶的元素与未排序区中的最后一个元素交换,这个最大元素就进入排序区,然后再进行堆的重新调整操作。如此重复实现排序 + +```java +import java.util.Arrays; +public class HeapSort { + + public static void heapSort(int[] array){ + //先把array数组构建成一个大顶堆 + //从完全二叉树最右边的叶子节点的父节点开始 + for(int i = array.length/2-1;i>=0;i--){ + moveDown(array,i,array.length-1); + } + //经过上一轮的调整,已经将数组中最大的元素置于堆顶 + //接下来进行堆排序 + for(int i =array.length-1;i>=1;i--){ + //将未排序的末尾元素与堆顶元素交换 + //此时未排序区中的最大的元素会放在未排序区的最后 + swap(array,0,i); + System.out.println(Arrays.toString(array)); + //进行堆排序 + moveDown(array,0,i-1); + } + } + //每一次moveDown都会把未排序区中最大的数挑出来放在堆顶 + public static void moveDown(int[] array,int first,int last){ + //将first的左子节点设为largest + int largest = first*2 +1; + while(largest <= last){ + //如果first的右子节点大于左子节点 + if(largest4.5直接插入排序 + + * 直接插入排序 + * (属于插入排序) + * 时间复杂度:O(n*n) + * 空间复杂度:O(1) + * 稳定性:稳定 + * 排序思路:将第一个元素看做有序区,使用游标从数组的第二个数开始扫描,然后将第二个数插入到有序区中的恰当位置,使有序区增长,游标依次后移,然后再把游标处的元素再次插入有序区 + +```java +import java.util.Arrays; + +public class InsertSort { + + public static void insertSort(int[] array){ + for(int i=1;i=0&&cursor4.6折半插入排序 + + * 折半插入排序 + * (属于插入排序) + * 时间复杂度:O(n*n) + * 空间复杂度:O(1) + * 稳定性:稳定 + * 分析:是直接插入排序算法的改进,每次都将有序区折半,查找存放cursor的合适位置,这样可以加快查找速度 + +```java +import java.util.Arrays; +public class HalfInsertSort { + + public static void halfInsertSort(int[] array){ + for(int i=1;iarray[mid]){ + low = mid+1; + }else{ + high = mid-1; + } + } + //将low到i的元素整体右移一位 + for(int j= i;j>low;j--){ + array[j] = array[j-1]; + } + //low处的元素是有序区中刚好大于等于cursor的数的位置 + array[low] = cursor; + System.out.println(Arrays.toString(array)+"low:"+low); + } + } + public static void main(String[] args) { + int[] array = new int[]{9,5,23,2,0,21,30,13}; + System.out.println("排序前:\n"+Arrays.toString(array)); + System.out.println("开始排序:"); + halfInsertSort(array); + System.out.println("排序后:\n"+Arrays.toString(array)); + } + /**[运行结果] + 排序前: + [9, 5, 23, 2, 0, 21, 30, 13] + 开始排序: + [5, 9, 23, 2, 0, 21, 30, 13]low:0 + [5, 9, 23, 2, 0, 21, 30, 13]low:2 + [2, 5, 9, 23, 0, 21, 30, 13]low:0 + [0, 2, 5, 9, 23, 21, 30, 13]low:0 + [0, 2, 5, 9, 21, 23, 30, 13]low:4 + [0, 2, 5, 9, 21, 23, 30, 13]low:6 + [0, 2, 5, 9, 13, 21, 23, 30]low:4 + 排序后: + [0, 2, 5, 9, 13, 21, 23, 30] + */ +} + +``` +[回到目录](#index) + + + + +

4.7希尔排序

+ + * 希尔排序 + * (属于插入排序) + * 时间复杂度:平均O(nlogn)^2 最坏O(n*n) + * 空间复杂度:O(1) + * 稳定性:不稳定 + * 分析:Shell排序是递减增量排序法:增量为gap,先比较距离较远的元素,再比较距离较近的元素,每次间隔gap的距离,并且gap逐渐递减,直接插入排序相当于增量为1的希尔排序 + +```java +import java.util.Arrays; + +public class ShellSort { + public static void shellSort(int[] array){ + //gap变量保存可变增量 + int gap = 1; + //由Knuth提出的经验公式:gap = gap*3+1 + //按照3*gap+1得到增量序列的最大值 + while(gap <= array.length/3){ + gap = gap*3+1; + } + while(gap>0){ + System.out.println("gap的值:"+gap); + for(int i=gap;i=0 && array[j]>tmp; j-=gap){ + //将"有序区"中的元素依次向后移动 + array[j+gap] = array[j]; + } + array[j+gap] = tmp; + } + System.out.println(Arrays.toString(array)); + } + //gap按照Knuth的经验公式逐渐减小 + gap = (gap-1)/3; + } + } + public static void main(String[] args) { + int[] array = new int[]{9,5,23,2,0,21,30,13}; + System.out.println("排序前:\n"+Arrays.toString(array)); + System.out.println("开始排序:"); + shellSort(array); + System.out.println("排序后:\n"+Arrays.toString(array)); + } + /**[运行结果] + 排序前: + [9, 5, 23, 2, 0, 21, 30, 13] + 开始排序: + gap的值:4 + [0, 5, 23, 2, 9, 21, 30, 13] + [0, 5, 23, 2, 9, 21, 30, 13] + [0, 5, 23, 2, 9, 21, 30, 13] + [0, 5, 23, 2, 9, 21, 30, 13] + gap的值:1 + [0, 5, 23, 2, 9, 21, 30, 13] + [0, 5, 23, 2, 9, 21, 30, 13] + [0, 2, 5, 23, 9, 21, 30, 13] + [0, 2, 5, 9, 23, 21, 30, 13] + [0, 2, 5, 9, 21, 23, 30, 13] + [0, 2, 5, 9, 21, 23, 30, 13] + [0, 2, 5, 9, 13, 21, 23, 30] + 排序后: + [0, 2, 5, 9, 13, 21, 23, 30] + */ +} + +``` + +[回到目录](#index) + + + +

4.8归并排序

+ + * 归并排序 + * 时间复杂度:O(nlogn)^2 + * 空间复杂度:O(1) + * 稳定性:稳定 + * 分析:将长度为n的无序序列看成是n个长度为1的有序子序列,首先做两两合并,得到一个n/2个长度为2的有序子序列,然后再将这些有序子序列进行两两合并,不断的重复这个过程,最终得到一个长度为n的有序序列。 + +```java +import java.util.Arrays; +public class MergeSort { + + //left是待排序数组的第一个位置索引,right是最后一个位置索引 + public static void mergeSort(int[] array,int left,int right){ + if(left < right){ + int mid = (left+right)/2; + mergeSort(array,left,mid); + mergeSort(array,mid+1,right); + merge(array,left,mid,right); + } + } + public static void merge(int[] array,int left,int center,int right){ + //定义一个与待排序数组一样大小的临时数组 + int[] tmpArr = new int[array.length]; + int mid = center+1; + //记录中间数组的索引 + int third = left; + int tmp = third; + while(left<=center && mid<=right){ + //从两个数组中取出较小的值放入中间数组 + if(array[left] < array[mid]){ + tmpArr[third++] = array[left++]; + }else{ + tmpArr[third++] = array[mid++]; + } + } + //剩余部分依次放入中间数组 + while(mid<=right){ + tmpArr[third++] = array[mid++]; + } + while(left<=center){ + tmpArr[third++] = array[left++]; + } + //将中间数组中的内容复制到原数组 + while(tmp<=right){ + array[tmp] = tmpArr[tmp++]; + } + System.out.println(Arrays.toString(array)); + } + public static void main(String[] args) { + int[] array = new int[]{9,5,23,2,0,21,30,13}; + System.out.println("排序前:\n"+Arrays.toString(array)); + System.out.println("开始排序:"); + mergeSort(array,0,array.length-1); + System.out.println("排序后:\n"+Arrays.toString(array)); + } + /**[运行结果] + 排序前: + [9, 5, 23, 2, 0, 21, 30, 13] + 开始排序: + [5, 9, 23, 2, 0, 21, 30, 13] + [5, 9, 2, 23, 0, 21, 30, 13] + [2, 5, 9, 23, 0, 21, 30, 13] + [2, 5, 9, 23, 0, 21, 30, 13] + [2, 5, 9, 23, 0, 21, 13, 30] + [2, 5, 9, 23, 0, 13, 21, 30] + [0, 2, 5, 9, 13, 21, 23, 30] + 排序后: + [0, 2, 5, 9, 13, 21, 23, 30] + */ +} + +``` + + + +[回到目录](#index) +

4.9基数排序

+ + * 基数排序 + * 时间复杂度:平均O(k*n),k是位数个数。 最坏O(n*n) + * 空间复杂度:O(rd+n),r是关键码取值范围(如0-9,r是10),d是最长的位数 + * 稳定性:稳定 + * 分析:将待排序的数据拆分成多个关键字,然后根据子关键字 + + 对数据进行排序 + +```java +import java.util.Arrays; + +public class RadixSort { + //maxLen代表最大的数有多少位 + public static void radixSort(int[] array,int maxLen){ + int a = 0;//数组array下标的标记符 + int n =1;//n=1代表比较元素的个位,n=10代表比较元素的十位 + int m =1;//控制键值排序依据在哪一位 + //构造一个辅助二维数组,第一维代表可能的余数,第二维用来存放 + //数组中余数相同的元素 + int[][] tmp = new int[10][array.length]; + //order代表同余数组 + //0-9,表示余数为0-9的元素的个数 + //余数为i的有h个,则order[i]=h。 + int[] order = new int[10]; + + while(m <= maxLen){ + for(int i=0;i4.10复杂度比较 + +![pic](assets/algorithm1.gif) + +[回到目录](#index) + + + +

5.查找

+ +

5.1朴素查找

+ +朴素匹配算法,也叫BF匹配算法或暴力匹配算法, +将文本串一位一位地与模式串进行对比,如果中途有一位不相同, +则将文本串的下标后移一位,再重新从模式串的第一位开始进行对比, +该算法效率低 + +```java +public class NativeSearch { + public static int nativeSearch(String pattern,String text){ + int plen = pattern.length(); + int tlen = text.length(); + int t = 0;//标记text的下标 + if(tlen5.2KMP + +//朴素匹配算法的低效:当模式串与文本进行匹配时,如果出现中途有一位匹配失败,便将模式串右移一位,用模式串的第一位与原来匹配的起点的后一位进行匹配。 + +KMP算法是找到模式串中的next数组,next数组描述的是每个字符对应的最长公共前后缀,当模式串与文本进行匹配时,当匹配到某一位不匹配时,由next数组可得知模式串应该后移的位数,从而避免像朴素匹配算法一样的低效匹配 + +```java +import java.util.Arrays; + +public class KMPSearch { + //下面方法用来得到模式串的next数组,next数组描述的是每个字符对应的最长公共前后缀 + public static int[] getNext(String pattern){ + char[] p = pattern.toCharArray(); + int[] next = new int[p.length]; + next[0] = -1; + int left = -1;//left作为前缀的索引 + int right = 0;//right作为后缀的索引 + //根据已知前right位推测出第right+1位 + while(right`_7ARyj*0?K*$~4P_5;4{bM@yqIF*Sc*Oqs&pINM5>Zs%3_&veF35meL zxy1e}$=R)MG zg|xRx92LN{Z)_i5Dd`FITFDrcmk{vqEG70yb9$W6U9Cyj=1NfVY`mxD(fd=qsrGhF z)*lty{qW$SW7qp=OgBXHrrq`8FjeJxHV8jxP33ll{p#whzLmucPo<4gLX_~jC-J&x zT3{zH^Dw(BOhV>_2^lL z%2`X!jme_FeM95fhO0m3rc8F~Z1Ld-arH-5mSwxm()0eV9>1;>Zd*iyhT?{cSI?Le z^8BL=3DSck@e)GVN2u@?1x`AZr3HqPa@e~E5)A(kEuSMv1nvv8ULU$1tf0`BC)?p_ z8D{7)3uX9QZlTw^u1=TveHKM%|fy1l}jV5_LoB!Ejfj~NqeeH|bYw5tNy zkJO>|NgSYb#ph;OzR|f$L7RY-th)0jV@3!>G`4iryhMMyPmXat-w?$lym4|&wzDwa$AwF*N&0x}#d2zQ9z)B1Pa@frSx~bY?w(n* zEXxo{Vh;UofNP;zb~OIQk830p_aJYh{|a_H8Vy{1K^^($x=>o^WQrgZMmY&4)ZBqlHoc@mv#@lKSkd{0yH1!QkdBq!!FtX=vcaT2M6$oJt@A#C&Gyb%TJ!Z1%1L6*e0nTP8Uf=by! zxb#Lel-?Q{qla`x2G$B%Jkd#KBRL@o0GnPZ3+QY;L8;mK=4?J;4`? zaUF}{b6yV%8REoK`a=9XqryJY=EGO!oqv4P=4K6#87;qAkUTz8fmU zay+o?x^x<=ShbWpTb0rje+o&$GA@X2UfDlSXk;}wnzQ!VOZR)d?vsnncol5M3)8~; zluQi%czH=L^sRWu?vr-~H=8bM`B}fdI-)Yx!ry-L7NZ`Y2&8x}p-~u>_F^6p!tOWg z^N7g}#B2c1&*`$227E?;;koRMTnXsgOi44j{64A%_Qu)$`29w7<26x}`R}|}|Ka2T zs67kVL$+q>)Lb-XZ0_tTYxL}YM^=8kJvl0|hHP|LCswF5maV0) z2-O$mZT%zwq=Aj>53(lN7>eaOBS|W(%E%E;SzIgFl8cdv^?1G6BUEj@ffQi_v&tgo z@0F~0?zNXn4d}+A=+!t_WHJ@;Eq;c>k{~kxgLy4xtN0aN9xx?yX?l&U8VLeWR#O3| z0inJrEUqCR2dLcElEkqnTRY$JB>I3y8%AwKb)eZu=lVT2sGx@mes&?ATUuHAD)H6S z6^zMHGMDo|clnwdbGf*Ehm0a)mZtw{X|T=wSuFw>_-`t^N60s1aG5mVx4+abq=r`( zUK$~Fjl_J{IF&5la)tuSe2oAR-VV%Tu2OOvoN97Lv2JTgaXrXQ>p52^|G?v*!r*&3 z|0jGz%n$~)kh_{dH@{_%OPQ0J+tQm$74Edr9a0!TGMFEVL;K8)*iS7Wjd(2M7YVdz z{*gs&sVkk_dw&Pmvt8}ZE_}}5>RoX)^H+`RIHe6WDUm!FO-TITWyJokWi0)$4N=>( z<=Ay^ay%4oFH>*(tV(T(UM(kbrILY_Vy=%%w3Hul0eRS0@bb~U6>*ajrX$lqL+Nz| zzFYgbJitFrewcPM#b1k zB+g}>(K111LFbL%T^FS<$71ChxHxN^`=CnMVtG~I(V|aOu@q?)nQ8|#R3RqMnX`VU z^DLFpPlC32lzh0J+GI@YX?v1JU*xQq4M5Q%{2_<9O_;^@|6@+(OgA7bC5$TWi&gQ7 zrF!#Irm0LSc!S*Di*Gkc<%vwOy)N;XJb_CFk(BA`v)|(^i73iw7K%%+4fp`-z6hrv zbhAI|K%oh#L)XPo{~77oI6u#XC&qdE^#`v09D72>x?b!U1>G`RA|vW%|J&GzxBg`v zn^SzT{9fuP!T#c-Lv~fr!$UvQu-RVQ5bNWYqqQ1lM#2m9t4Uu0*%?)u>RU_G{tymu z`5)77H44mW+6K?f8RaBSwFPumk=P#9$`EQpxr~=L3mL8a_}Pjh$-hKl-fihsWU3V; zRxWxlLkqf`N@HZdaG$RpeX9GCN`WTBHIADQOzd;bJolX&uyXj7Ye!GNzsiK>2l=v1 zLv28xWL3cqHdt{oXr!)zHd>LJFF&JBlgMVL62`pLsuNXcU1>pgyK``)qxZE7y5&!@ z)?46-pTLfTzH3<<5u%XY=#%trNGFb=TWl$caKhjT;@Z)1k|5;{QcQm%)1LoPI{7l_ zi!rD3W=}!^wku!@)*EhS8XX|m(LlX?r@gOn4GO#ft!|zi99Q>P*cH-PbetqnG z+ZA0Xg_nRsxsN?L-6uzhp%FCVuoW=UHmU7vh- zNAK#tTiRKumRi-3kM48&Om)9NQcmO%@wVLcb%n zu(m_~!pGnn*Z%-^^H!NP83|e2n&)w5KhBIs9cB@Eg{|!q_DoE1?8}6_p&?l3el`-< zz&aQ4uXA-XT7F1IdiJS!I^d>E4j&H%mSnpG`zqQeHX?puSGXvY>i*_}AMmH*X!V~Y zrK5yrvMZM-wtU^Xt5sff4R%=wt|znZGHA+whcc%Wm@v^Ndn&AP^cQIl&D zeuKVqY14u0J%)RgtZqENe;6T1sK$_~ z<>!i**a3|;Tqzo)6yl;BUB;gdEr8+kukiI|b+*vFnKLkVSXSZn4myBnq^!u&C=XJ@ z4RC6^UKQt;BzbF&VebwaoOqxU5CuOB?vwetAr4MMTx6PD;j_5Ni|a0{IWl#yOx*SLEj(E<1v^*!e%T&UUXFNrq(<7$}>4 z<0X|ab zR=iOoF;BSDCCO33gr_d|=U3$gzAJ_5x{6TEiOf!fO$VpZ<1W8!kK2B)MwW9FB+0Kr>&ld%B^hnU}edN;#3Io7v zkcaiP5nE#8=``n!f~0!Ctlf0%E;_|@fJ-{J2{IZBR^N*|iqq$?$3%^Si&6%xa!IeV z42}`J|Bb>`=y{(6(3R!e{_}G!e1#gbV{mrw8MX@Yvk2PaY_^d;ZwHZO zoU2Fn8g5dU5kG4ryf@qxK+cEMl^xz>fvc5zV1eqF1e(|X0#zSadK&vOwek4fBu>7$ zb9y$0FwH}%%c!n%rH3((DnRPJnyLCm1~#`JhBHzpGb3rL3#Cs@%+tDDY@xu24V5!9 zI%f{OS;YpkxnM7k2jit{s@i+Z#FIS!0zXhSHJeA9e^Z!~GDA3IZ0W<;q&rJGn=WyD z_AAmm{D^Vu7SH_X_l8`E=oj-kYl5UZBC@OS5zs|%Bu%fREJ8BDio^@vDRvW?VmIx{_zsK^!O?zZiasnEsW@}(LHV=Y4cT%}QvvGbY?9f?R9p2lyn zzIDW7<6_#9?E}ZZNMfo+gCYEry{YB+j>SF6W#l#Q4_R=C<#&BTFzYF;Pl5}9&haNn z_NvT~HCi8?HFwJF2{rDqdaJZPe}NMv{vP5$aC+Ncs}d=p5;?O4y6hV3PG=0Ztkr^ZsKIO@Zj@3OW(zn(mOqP2#{L~Iz%xARWrxcW8IzIa61 z=VLaB^ zWj)1|nU}`v)H&Ytk=A=~{DW;NAM8tu-@;s_Y6Kf)x!Lo!^@FkTpBYQyva! z8m*h|*=bE!qdt{{iboLBRYkKb>?S&j9lw8|{bGx_f+YAO~mv7;%IITzzCZBM-Fi*)gOu0xP;@Rp-h+JOyq0 zA9#q;skyD(T0Fqrgq8Q918UZ-fla_v6Tt=AoA8x;!8$BL&W|nAg}?d|LYyATOuDG$k50m1JQTyAf^eH zJM6?_PEuXy<5woYw?F4=sg@M;F>k+;KcY%w)qG|wZ$IB2XI3zCNQpi@syHg-NQbaqsKV?euU#!ilK-0`(&Jb%g(XaMr2>oGKG)JpJ$|A_FU?VZ?Xcmo+e zGcz|@-bCtFQje!B6?)NOE^o=*z5J4{Jm~t^9v!|ECzKEfe1(q<6*CCUNUVJM+Dc2^ z3HJrhD-A9-{%AmBx-}Tb{chmfBJ(kkyg(mfz+-#3D~2!9BYo42byb;kjFo$rYH7}s{hImy?G(1ekZqCMovS_LS)bYp z4pNxW3X}GK#;D-QB87OP$2hDfI!5&xPAQcy=O{rI_W0K|C-EV-jj z@)%{x6#|pU=_pEN2XbxE_8$Xv5Bz<=jy~_X@kdfn`bL_t6W`x2jn)*2d6re%@8jlm zn8y`RS34D9BZa-dC}tpOMK?A5+{wpyX1|+?X4mHHst2t1jLdXqFX#_VexVs_+_V;m z8RS1qLV8U3W{wG%?P|q>^5_Toq2U;_5{uSsjU~HPsFn$H1)gU?C>Wou69o$m;p6hi^0yFMo2M zOuv}9WBW(23%$gOHcU{yhh5X7fzK(O{rNc=t zN+(DA&&(K@-eV>kHbhbcTkRx9Th)kJcj|Z{#t|<`!o*s}DFX+dN%0Vx?lMc%-?3GZ z@OEowFndgJ&X1_@A!n?Gmv{{QNtoC)U1Ogpb3E(>uFZq!CAvY%30ITS(1%!)9ghos zWWYUM+b&=U3L1YTwD709pA+U)wVxG&3$Ac*of#nOg>@1{+;!&`I@!y{+GP**ws-U>bW28 z`I4E>wrThMPV1XXmbRbW$-XR)S?U;2X_Kt7{`C)zb^zpaYWn$kS1>$R>;K(-_V4w8 zgN~Tsr4gy`wds&r_#aIo)-K0Sddf^b^9*S8=l;MW_hP35h6Tb81Z3Bvy=KI-71wub z2K+2PWI2Nz?R)FQ(Zth*6GijNHV)7u>=|2WeWF>}EOwA(qKl*+IjqSBS{fBBq>SHW z3Jk!ut~`A4(;hxMEOhoJ>@Fb-b`}zio_OH6weG)U=tS2#iGy>%jwn;K>;i%Ye|iHg z)f|EPFV#p!#%pAufRZS84&M5ANxSz5g>6(*;u@ov7e=;VAuT}S8- z1WS@KXxtShjc;3eC9BgkwE?W7lpKTmOw@E_O51NY-50OFP5-(zJWb)6@YZL7&Sj@C zw}sOrgBuDA0D($i^``=5Mve}i{D54*lTkKdQBh_d3Frraf8|8sF{!#CCndS;LyL}y z!g=DyZ-mx`3xR>oGKy}rOqD7;MH|_hz?IEIq!MVk!>(KbUn%k) zH2oM-iQT4?W_4~v`@AK8IoUtImX?t^S<`eTFh}PHLAVI z%=hfaorqn6^1y|rWuh;DIW-jjeYP~~p$#q5;{2CCRY*9*{giKAnZw`osnI&e4s0n$ zn|c0eV4kz)U-#}4{saU!_8G*g5HDq~3wEZjx9y=-xuYS%u$DH?ueK6k1=`DeF+G`cPs4h=lQ95Eoq_2jD8cXjI zqLaSV@#z%0_em2i6&%n=Q4fG0hodkQ#^=nF1+H4drFz{giMDGg-#l#y12sSw)rVoY zi6@c1ait~7God7hZw=qm9CDPdHHg=`tp3frW*W^(^)-9+aIIX+x6eU6=~W!QRdsh9 zZ|b|2q@+z_qa`KmYyu35N)Yh{FjuKk0TaG`HJA_(%&OtC)2h!)VU0}2Qj#x#Oajff z$dKVNxf6^U@syxOM3fB`bF`*3{dNP0uY$S7|5mVt_IA+P!P4(wLhjMx&8Yqt`gDla zctz7Xx2Edm1C9EqFku_iz&iBI8VNYV_BR1*UOr+GBSY5CHDMiH%aC-QT@M;ke!ZAd z$c>M#j5K4p_jGVuv8-9eK>H9!pg@Sl!-D&~yo7{QIwf1+PG8amjXK~g&a_?yN zU60dqmI_wQt#Qgjt8KT6=FFlyKE}Z7AY;zS=FbvqSLXB*98y~!Gj*5X*M1y+4Fz^? z<=l{q=jo8Z1NfhS?LS4>P$^KQX~chcVF1ju;DAb?_Cyc;tfl=@NOBkbwh|+~%>s@1 zzyhsjIUP;V;@AGP@NZADtrA}e8&U8Tx7tX%e^AhT*iyz<<{3$XxO7=c1Dy~MWK7q{WmQVAxoy^@h=CexHy0VX&@b2?BL)t`3B zfX>XMSYNPeSxVll=3VZIA&-WG*VFG^KhX?Fs%oAw|6!b~h8TTXBR0N&Tk~=v|Ja8Y zB$CpI)P47h!2*_=Hm7J`_ok1uBD?P^Ju*emrlmoYMq<@vUX5t0x3oG$?8cE#p*e+? z81fy+BG(od)Y>G+kxMCCQ=v0`=_}Hy@4Tx~9cRYq}4gNHG$kgn+ zefy(h;YxpyE%D3#EEkjI#F_;`dyM}+5y}Ms*J+Ud41WO(vNebv1}+tkTNP(mKna64 zVFF|VH;bE*<=6AWnq43_?n*q3N}jrUxJg^p3){LEij~9=V)4dODk#LqD!$VqK@f$5 zt1aIz(6U-Tt=j_lyc|y34}`jdGuYy%_aKAiDYT9I_aCyEHrA#BMhlN&94W;O_C&;I zexy*~N(#wLP1t4)7JW6`(|o$?3aXtpgNa5ILJ`;d$z<9_n9Z+-t1}eVE#LB);~M1+ z-|-eEwPw1#shzzY&l0CwI>11VU}OBsx$^ zqgD=|`l3j1@Sj8o$e!~nIjT+Tq_}g204@D*^Dx6j_Sa_uw=?@W-9e7kH%T?gUGNYG zFwtgF`vX!GH@M@uXbmqC?~xHJ3@3ATGKQulWt||~{TX*aA}qWHS>16_KR=(xxf22L z8pX?94L<|<=F>+UXF)SQK=!#1U9Bm;=y%GM;rFeOo<;9}bg2->WlHy^-|O|54mL1} za5(r{x@XxidTE|%R=T+cGW2PT92s>LG*>Z&ef;EPe^ckbqm`mlTZRZt0V#yrpH zI{Bl9&}`1%rokJNshX{W?;dMfmYhzKyQV9PR49R;K8`QlPlue(rk>B!5ZjwC`L7xn zN(y%P(HVWP4(^~$ACm+=r#4nEE$C-*h>5hKhWB_i*vUg4#C8;-l!Ztv2f_+b3>PoH z&kH{tKx98v$zC(EE=+Mt-GA^bIwZ~_L*Rb4d)vT{qa-T4%ZgF96%_EbqPUmp{DtX# z^KT88Spu%^8>}aX97o1koa+9$#+XujUP`mr;HIAZ@(;p7%lTa^JsgM5@zq}wtKe?4 z$Y*c79u5*io_Orto}l{{&&W_Ssm*ScsGG!r6_Mkcl;BnWhR;NkBPoI~a))1vu}kPD zZ4n`$5M)jn_anioTy9cMm62*vM7vz}&=6ye zeST0(qz)Un);HlouCG8DqVV#TjD)Iw0Ie2mBPTy9}wWtFQur)VrO^&wSI!*DVw>ck}lJNyCZ=Sm!bIZ3`sFJ%M zBOWE>x*}R3K;flMhC_W^W~Se!Otdbcajd~L)10Cx09Fy%cP^AFfC<8k=H*pO0*r&snlZ@AJXk+lNwm_}c4_AMprq zLAWH`1qf^Eo~Nv=cXNZa#at<~Ry0%n_0M0X2CL_eB-$;6Pj2*Li|m}?&gOYozidoY z_`b_!&6I|B{CQn!foO%hkU6c_M?srW^2i(Q_d$Y2S^{r7XKHWs@0D2PJ@|%RdAy~_ zT_61g1&I5~W%3gpnWoW*0<462rOdrJV0s~N6miZHvK7vKL`May_`qhmWvoWRt+$qE z@USlU0AKjp;Ub76v-4>qec(2`j(=niGl zQ^DjUFa%ivmP*(PSCgsmndz)C(92q#OyIsUTI5^yyAJQcEoqN$W?%AC&f|uFit)Ax z4gMm^R?!3wpUMr(!Tq7`%wOAMX0ZsT63k%;9vfk0>{fu0nq;oMiQqAB36(p&q!B@3 zfi7dU)ct`6@TVmE&ry`{sneEVJDF6-nTe!ko(>@-U@2P(m@V9AimPp-p6hGgR4V4;<%@}n9`-tMo^!$DSwT^XtU+0ifp$~ zHz%AC6-sBtm(abo&Cl{BUAnSwTAXS+*_C2zY6RcF~% zSv6pZz=+wDZxJj?8RJBnba7iJ%~Oedo?&-W(saNRQC~#fD4~=uvDjO>{ex$8dQhlI zyQ+4qzk5>bq}+fGN0Ue8=L!Cjqfs(Pb+w_WdoVxCI?}yDQ<=41cZl)agkrfmc&}m^ut8gm)Oia;JX-qcDy_ZUrO8Bf+huO-9o9u0Fu+!cI zmFyP-r^KdSr+kY?P!^Q-*Ma)%uI@>#$~a5O_+csqtGL>cLRDtiEJXgVh$dyWQbM4X zGKV(rNQhi+du%R3+}ki_M}zf@D(%KU?&OZ%Kqxg< zPd#ThqRN9VkEacGSG3k?Sf@qxf3V_RO$b-2@|}S6YEw^C@+9PR>lY^73}k^arwYoF z7)?PaJ;XwszBpot0YDL#2sbwIn$haP7i!r;2o_BuG~9?aGm`P%t!jQhOLq7e&{(lm zD|cf~UJ5(rLxq*kb39}7wDJkh{hgg=q_sxM(LFA8mXq$~stNo3mp(Jzk95Q3*8{+Q zAsY8YZW9MxQ5qNFFG*2O#+^HbP9!R)$$V!K)_MeUs0d&LC%#$Vlt`@+6VCZH1L|f+4m#Qo`%IWMqJU%Jy2}iy`LhQlgeD&gBVtSpC+s z$~IMx5 z9WmW?;bq}Mi*@Wf17jU`GhRDB<~mzhmX|=O#xa81v@~tsFY||XgPQraO`GYvo}Ji< zsITW=`=5X-)nsa<6jG33bVdqpPsa}mZ>PjtvaVKbUFJ(}PjCG@P7d&aC0|-AXTD)_ z(33Z3WOCxCOLW2h9)Q~J)j~<9M5i*1eyjpW^GQy6i_caLxq&iTvG2|^L8_Bx74->{tyWXRtA%x>bVZyZJVhc-k z)MuI8%cM%-I#+^2ApZe`&b*jxgZYzs{x3?@!7d%OPChPo;I&7;7-lHFup4LL~Lk(?b*nlsm z17u+(6Q#YDvHbbMh@x}q)C~BbsN%iVDrQW?G&qy@dFFRlI;0Q5ByC*tQK*s@MJ`2t zlbz@~X0C!R&v%b;uf<_gs?jasPs2Z9r-b{H@4nX?3rB$|veUbrGFimR_nMh%bFI)H z0dW1U%?%SQkR`>=@ueFNnI}!7XU8fsdSg??0X$Yt$Y%mhu9NW5XUy4EiKR$HaG^1{ z_N~7JDPD6uk@_Q}C~O5~A^UG=KE4L*4?dMdwH$~uBF-v$1h!^PzgKq7}y1^XB?-eTwpN_99O;_9Q7QC=(h zSp={IhAz}>ATY-&n)Zkeau0Ti5TZvb3^PCf>c6njEnE|-C1W0$R`@z@5B7>(scaBj z$dy`VG%z4^e-rufqI3(`k=20@CP_>=dXMSGJs9H$Uqbw`odd3s5VpbeXW$=8Kl zd*j5b62`aZ?x@AI~`=k6n z&DQ2rN~yeC{3}3EhXSd7_+w^$oNwBZ-^K~(|6JAH$6M4&Yxi<48R|E|-ewl2z<`Sklp0DT7Vhr@$%; zF>dyiAH4nH6Pr)tw9JMMe$yQuCFf6@ew%lA_AEu!iNHqcu!ksbLcKE~Q}|H!se!)> zmCOpZFERvt|rgr&ht zSSigic3p@uIL~J#X0TV}*6n^1nGfT>)Uwy#(Hn009Ww%>30%7o2O0>k)hPdK4a-IqWie_qVW{aAX4~^^{)iIm3VL&9~}urZa(r@P5o{At!p>!w;nnvMs0 z`46=#rLqd#n+89K24m@7#ofPOega0@5*GtIf$-BCBl1www_N#zFczak=ttlloj|ik zm19830u94n?V}#V9>cm2v7!XFP-hZB9(&qiIyy*CTy|ScIqR9?9^txhb)c13-|W)_ zSWNkD?bujOT^LjpsT90xGG=$y9R8~?B^>v~^D3V$3i!nFwkX(ZZ(R{9B|&%*R(GxB z^oI)W?96(Z`K`X5y0BZ2W!RgHo*VN>z`6y`E7t&=v0~7qAB@4sH3e@Ci?3kWM4l|F z&({udZDrp4%|t9!t^G~MJ-z%#KkHPaUJf3Z-SINcbaWe^J7}aCpG3a*#eauYBL}vr zy4IHIGX=X_&&M!AO?cu3bFnRa$V=I><cpqgPHE;;mH!f_%n4&~iJ!+{i@gwp6m1x8cN7GwTX&8-t1?lUImH z@qE)rqt{17XgWz`;lC9!-hpv`>O}cWE{hMWW;RK1ayo7s1(dWakvm!NH6iW|z#8S3 z_^&FNd@_*Mzyv|(F~W!-!vy<7@0mpF>oK#3WBJVc`GQJ$7n^1(hOkXs(y$j+Q+);0-Pb0U%yFX2B1E=h~cK2~pne8C0`?S|iG= zVgneS9BuhYP#hU=8t3NYp>eu^64YPwNt+O}zjRFGBcPGw8wCVRM#PZ!AM^K9wxY&H zMBc2;@9i_h>z?P1v4ZHH7>zrwC{U`hGj{3zeqxt7LWp22h_(cGu*TE*ai*tpBXx;M zqd$yX`(xS{L+k^1!;qV&w^tu86xv}>Qc~j<4i?h+smyOl4-ca^t&j=vDDKPGikZeU z*2t6t_TcjbOz7PMr3(+eRT@$bW%z*gpO!TV4vmXsYhTNrS3dKcWu*vCq_~2*nPa4z z#;9GLGpD0RaP0v25v80p-3O3 z1Tg-Q4ux^IFNnG6@tYokzIHcen{IClr8wYG?9&Z=nGUs5>R4?nu6Q3w4PGDhiRRyP zO3;w}WRvTSJO<*i?W=>kvLcKiS3>?$7=G+fYxFa3wBb8hp(R~Idqu~RjneSWjTctj zdD(szjavjDW(HzN3`t+9s>@d71D=n6c;R&2x;C7xbdEj=nCU?GGIagp+j-$qUpEc- zBl}(z0h5xMdqyiVr~n>*9b}4?bpn)UYAR*XJehr5#y&8-0_hW_IiUHJ5B(~9J#Q9?=_if;PpAfKTZi=$nT)=&IZ)@ixPAy*+Y(DNzNO>F|!7PYSNOQ z0w{+z9g_%qb)qp*-wX%pTFEcuE^nJstpI^iUCzh-?j>Yb_P&Yh@(*LV;)=~x^XUBH zVs9+zOemgo4`t`#l0mE)R=@Db_mHn_N@P(rin^7&5wh7(Jm?fZ(!V|LRV?0GxSD#> zA7c9}iwl*H4}4>&uGClPDkWbaY|%7et`VVOxR{YXT3oXOZ!0eNW2~&?UJ@7xD}aS`F+a4^*usVU`SOCSwqV|`Swofc5v(sN8<;3 z4OsOPa=r+AJG-Rn1&VcVa^Mk*U^YWx?lm@~0(X)TYK zO?ZQi88GbpO*&OjvX5@Eq-@e*DS=Dep-VuzJubmc>=2B;?*UTxyPjP{iH&OvDGeX} zJXTjTHl*7B&Z@AyvO=`c;<|KB9)zt+nH-HH#E=N%xF{N=2w0K-1KdW$vtBW9jsM={ zUGd5jIz3BWx)!D8v}a_U^GsUl4TCh>ugav|gU?fj?KQ~PM=R#brBXFPw8W~8G*3Gc zju&iikF_#Z9)FwWP#;H+OQ1MbNU&_z?2vpH5t}v7)pLsmD~eWiL-~u1?s`eMb7X7+)^FuY z&CWpKl}{bVBE;7;nFM5BO+#J^E%YpBKdn4Ses+VCKJP(iEX~?S#_t;NE^*A5cNN`O3R|%q!fEGBKS{T(YILiD| zY;FI?vE%(4^$#lW4)G9dUaW$fIlg9x!X&0B9$dEf0ZF!kSoD9Yfj!FZ@X@Im3^fKB z^Mgf2yJ@;4w^TAtJ5feqcJV<#y*p`ZNa&VoCs0|EQ9b-Y*NiJ#X#0)xdqwX1ag{D54CnnC677lVpBaeNu zKHg)A{x%Z$*sG7Ki|D-t)$Tz4m~RXfd^Uk1=-aihS2OOuMO1iHo)EkGvgpu$d^rwzsd38w$&A*$m?{{Hdq_ zv(qS*NIyVCR0H;3Dmu@E?Ag7qd9TI{**;ZuB!r|y3E)A-1OqxqXqnX|ySwj=j<%-` z8w!=O(oZd;Bvpl{G83`2rI@s)%fD!lAEgu{Xj&kkW(oON;F_kxUq`fXxVHOjoS+0z zdAAG*D)u7Ca{4s|BU1>1D2t|Xz&=_9eVvbg*-}#L9!gkQj->!nNkh4yz*E6>8UywKCl6KAq?P8GVo=ybL?v^gt+Qbn(KgK8T+!Nde%0S-a4f6}?06rkh3vQAc)f)S!`~~kb#SeGLq9Fn zl)h%A&NN8@cjsMg7z)r5SoR)wv)4^t73iKUynXhrjjV#Kv|e;>18X8DSUW9aw<68W z5enq)P5G7L5+x#hXMFE^ax+Tqwh-gIN{?$v=bwcx3X)P}FHMo-OgtKJg2xf(N_~`h zOzLJR=2)N1L^9mmyCx%fx5^O-kQkVu6|;Tx{Kj#x66*y*`1e$RAwMqcL__Q9coz~QjICjZ9P#fO zcj~O%QoiHZx%EM_)~)*{+~@J-(jV?FO$V>Ka${Dn(nS+}GAMC%U+%J5;J)69wCV+^ z8kEtLa75SzmM^dx_SX$IWh-mcr6xY$_p`e*7mGzu_3l6KkUJ7V9D^mrr4zZKFF&f} z4#kTHv>^OQ1Msqv3%Fo|Tx{cxSc#B}%Mf&_}b@k%U%e-!=2<8|-S|;2Hrli)tw%eyiSfmn)a$-h#ANIFdwKW$~yG7qcgdrICqtNDx>OBW{$ zA2`Q(t2zuNF^XazPtN>C9%D5O*q#8n4B|@+5l>kc;#Y0=1wMCbw9QUjuTUqIc7hy_ zmk|17Rj}3Fp1wb2IJXh_2DvUbn`;whIq&g<^`XUADm8a;oAZxVlaEGe z1%_0Nu{X#%pY*RA3^UpuSQ4d_8@%@?*oRAvRb#ufCyJ$6Flb2bT3Y-TbJ#IFw~C?d z9)?A&oGgC@`i^$db!$)NYhW2g0Ha2!qNG46WuC_HgH^JP@;H{tbNEZ;y@D3b zKl$Cq6!ChHBn=X+6+3o~nKHXwX~>%?Pw)@Fz4Up#LA7d$i&^yQddA|9;G2xvU5hn# z3o7U7gHf@VJH@~kg@Dfj0UNa9D}Yu_V*}0ZcY2FjG$jtgU*4I$38`-@80yCRtnp&Y zrylj=u_*R&Mkba_dP{AIooa=-Y+*arM6a({+F2LHzPJqb=DKHg)0h7cdIF%)iJc^G zJ-rImg1Y=ZHDA=aTpRJ-ilhB2zD)2oZUX6GDc^5@pZsQ$KzLnOxUat#AJjryB{i0U zPcqKmtD}$V9R=h#I=4)n*i562B1bu8hCt>`6944{PwHl1$0FV}31$*czz5=W@eaNV z0Y|0rf`O+$HJx5?mcVPWkq&Cwv3n|zD}#w(DSj8Oz{6iy!ZYr_vM+-Xz)pk-RMXME zneWRnG#LAWSZw7ewL929;MYa`c?#qlyU#7h*d3Tg_g}`B=`Z8!COdnG{(l^VW!q#b zQiAr@0JlN$q$fMjp!EYzaU>w?H}hL0W+9#;aQz^-&M*hl^%3K4t)2?G#y%eIK8=tH zL}D5IPOMDzUr%{pKqDfr|^5<9Jg*<`9UfAdNLUG0pBO z&d|7~U*|~7viomQsl)OaG8$u1#d`;5gE#fvC=K%8Yc(use@Vdj^9XrT0mAV+mY163 z(5?23YsB^;HoAHLeRTCqGpv3yjUDH6LDvBYnNnYEAEXi8kA#S=#sjf4=|I~-UV-E~ z@f0PC9LB<npgN(y{k_#2=99=|s9h?~P(ODCCzaQK4R5R1z zeR@rv$a3HcyE(aG_Oxf^o7kK#J{H;0&qTH_Evq^9R1HfC^shL^2X=I`C!QlH@0npr zMQZ|mu%)6ATPna#La9iAv7F`I7W26nY+I1^{W}g?*UC6eEgk!mrG4#pvzKS|zhB4l zf-6;kr`#uw{*?RJL*e~*4-JA&Jy9fMkrwHk>wzhZ&#MW|vRQ@ghpCarHj}1tJVSluP9Vq{P z18@7!%bfHX3cdI?sQoJm1iOdjEXDs~?>!vh?AEq#kqAcgQKFY9qZ7R*YN9hDj246# zqKoK4bU{QLJ%SlMdWo80^gbej5ItJ-8s)p>-uv0l{p|g|&-({_f56OKYh7!dv(|C` z&g0zJ&1;IQw7#lDcVN++Wx}@YWNDZkB}W~Pb*=+j-u};)x14-SN`oZ+ETGf-oBJ<+ zgq!I7Mr*o{Uwe#2lYcLKL~Y6b#=Ewsa#JH%hTUna?N2ln(4@f;qsssLXpDiqFpcQM za~~{sq||=m1H=ldA#;ZICUWAGDN_sblllAdXOr&jMA;`Bi>`%Ycjt)nInxg2-OSf4 zjoCSAkYc(9oj}ne;n=6oK3lmy)4wVn_rEXwW4|Ezq@WXTgPhA_YAi@KAAYUtr#$kI zpkjOV>^MlW#_YV88c<|r$m)37@{#~aME z8|fzKe=w<=Ebww`M@GX0Fir?r-GpR`#$ zc)xh*Gd$N9D2Xsk|=%RuqS(joKj%R=vBtN9!uJtk|I^bI*v4DY{MBt5A+_NSjp}|E@8T zjE1h`?XzONH=W`U<^iM!k9$Toz{vi%q}L3wNqk6WkfqO~FLc~@I37qt@0KFf<_%zM zD+VGU=tFr7I}gdMeYG>XM&!RrGxUa3CYf_EBKG1{8$ryH2i+f+$bT9j1irTnclEWnIAxlp6}*#IUnaC> z?i!pxbj|8p6LxAvWe*$O2~2Ti*V@F(#HolT6}x`wv29Sqy8J|SGd^txkBK0c(KqPz zm`WSr3z7_@`3G~ivCa>2!7{1ZfF5@f4%0*(-Ai)5$uMoHU8~iOwT}`NWQdaMXeUxu zm$=rEU0g40sqS|FMwS|8gy5mEc3#ZQS7(d6?;VZOT=I!So$b1-N;-}QL8+80;F@t& z78yFN+g}N+{qGa**)3sC5Vj2@Ag{J0N~+|^&% z`!h5w-w`9}cBNV!bz$qepcNOTm}6?O=F=XSVcVo=e~niq6xUCLdDfq%c^*%Bz{ifU zLr|9o$5tegH@U>TSqxi$y=@Y?B-Z(e!x98UUPU19ud_fit8QGbJB{N7&(}!*9an+` zR`f{$mB{!5xA8`Vkc|?~wGvvEduiQJD23an`ygB7>)#DG#ZcFI;M|p_71et8zunI3 zfY2L963pJTs!&UrO= zg4xQH$e%jjuI5t-rjz_ldo_<6wFpx}W-2&G1_4TZk603s8uh=^$hwD|Z zNiN;|EV=XC{xoY9zHZ)6oS+Cc3RNwUiXP!5gbMh55W>{zVITh*P@f4$yh#tAWh(W? zC(7Ced`!61-nII(@u@t~9>7))9kaB!R9NaEdYf1W4e;Uv_^Js|y^b|J%iBx-4l8W* z+lfz-(b5~>iMQ%BIgZgnc%2*FC5&asz_?7Xr09Y9_RvD&jnQF7LagDYLy-<|X;uEV zLpJtMukctXt9Nzg-44!B_YSjQHZAWCA^!+I9ZL(h@l_$ok!s)f zS%#!jK_=woAoTJuL<5IsGLbt*ONqtrIGKYVnN|mZx!C2aaOAZme|WTjQ?{vzb{P+2 zn=L~E6rErxlAF09DOe1=Xo}M*@i^76h*FIAlFI5;?PTt?@ii`TKHd2u zrTu(+<}6wI&wvNNeDJFm`r^sEhkkKKGv&DjMP8wY z`tP^icNVk9fwzmu+flUcj^rO>b*d2kdC2vBO@H+PP_Q@(lGE>#Gzh-kA-4PK68_D` zn2<>^Jud}1Sx@Qi*P7n0GQX7O%q`IHE!0E^}lnhS(I?)3xRJr(PQd-hGW#UJd{ z(_af+t%|!iGt!=}GRxUQozc&>*ToekCHYkmXf5sM#FQG9@EevA+c>H5`+F!Zx>NTe zgchAEg~R5aE@i8~c6KJ9q!&ewW}{VLmo+t7ebIZarU-3U@J!!HLOA2x543@a|4OKg z3V@HcVgWIhcU5UQ{%s&^N)2NLs1j9RQ#9oqR>HI+Wg zgk}SKGuIT621J}Rhus&yUjBJ|9OyCqXX|hE9zSKRb;(dmVh)4C}YrA4H~ zFfy8!F1}pkHaM-1U}KKR?TnS049G0dXr~F~HUqu7wyR7o82UcRH_BLEZT3-VKCP8# z?c3D5iSIPr6q}z8@S-1+Atgxh=3Eu93A}sl{vUORw@Wdn)a~lgD!Q7N-DiOTZ!Q%W z_H;CYzyjLuoN+Q*QmCP2_cWx+`uLH@wGXVkbxx~UqiBSeTAwI&Lb zDznz?knFiVS}4X#x6b_A9#l2#Wl%}>VD~wrbGxSo<2}|$;WxCpxr;ZvXi?zm2pU=n zi{gCBGdAY5bNEU>t^pZxqRK$PFY04I>A5E=^c4zapJgTPM zr%z5C>hF(GC??m$YL_hVFDT31qPeG69)6K-D119MJSWJdw^XrglR%~E4Obni;bx=m zk0H~ueN{z-d?1448rLw{ZG-dC45m|eZ7Nkz?rVvBb_*;ZUivV%_SF%ecy{$NpEix6 zuE(f=u!U59bM|ND401%!6IGc5+fMb{(h_~Wbjc>X$5wOI^2p~Mbj--H>QwRU9HE+$ zwQ7$ie2sgqi}WSl*F^T_peN%yxqN zfqX-PBh0NB1vlBa&4EBcrNlnhPn?;1bGVhNwh7w-bqz(u*vI@*XVxFxD3?$&9bb z=|0vQA5OVp)9wrz;h*h99t!7^5zkUv2j105^VdXC17W;jR9KT2oUdQriDvU#WeVW{ z6cT(~u};eMZa!d{!WvU5w;4gu!@io+#t9;WP5HcAe&X-&5~|GZmwV-Ucz# zfWl2=Et`@}^urcte+QiSa*r*arm+2zLWE8#wv-PKiBIeEa_Tk&Gue>1rX)XJPfIqM zrCXD@Z5#U|8!oKH@23uIIbJ76g*d^$`O6cR*XI^}5z7hlqDvByvZHR29Ga^I8EhfZ zu2#|6``<(P7c;`FG*-FyrxUW(u^9IT%36KwQ9eA`vx(o^RepEF=@s7OC?|+qHnnv}oBZFiLhx(r>|vBa;G|L#l~r-3}>~at6cDE23aW zx(b(yyRj=BD1T~3!`?Kavzn>5@KI~C;Vdz}h35m&d%^<+L{P1mkKpA*Lg;(_$(H4P z)})CCs?glHd0gvaLH4^;PVRT^@|FhbKYhqgeyXf(DgFZ4*^YdJVt}qSy75Wq%lH{+PCG{kk7xW)td6v>t>Y=!VP8)p1wy0HNlYNLzq#9u zopx_hpsC7m)kr6e)k~uZMzEv=e1yXF`^Jp6?_hyKJPW#ov|V9;^U&O-QdO!s7mftM z)RnDROVU^!#}{7&oo(A3AC*6lu8yed#Vsd3@8D(;i!n$a%3yXC$ZB9T61W)iUty1Z zLxdfrd$c_bp+eq6kG3oyvf_28GZ`1hiP%(DwE?iKqAdZ|KmXW)_cZoNkFgeOTA&d= zCKfP+8s(Duraf_l+_QjPL z!vNfLcjo_f(@i|m`^%&+DHI}J9q4=3BpZ;GO%`OtQZr5k(-L-!%e>*aawTYe{pauf z5ADL(#*$7o9H8)3F#D3!;QQq*k^#HCd+T5h>b|7#;M?eveVr*3fjNmqTm$&pR-1af z$+8p;vhN37%$L8ex4ZJav6)vgtfeK4OX-+8;FuIAQhu#3cF$hRy%jjwn zTN5e(43%H~qap%73Pcj|8;yTvY~o6@HAReneqL;KHLYg=m6vR}*gxT2Q-(>wz(;FH=%SDIRaz?EbUJjo((p1->0|8pJy zBPPcFS{`aZ*BxED(scoO1vm!(P5fyPDt-OU5Hk-5IG+IW&dc@R1suTc?uF1)(beQU zO!@yO=kMy)zfDd!+5@chI*=MLDhaeWP~adr9kQ{I+V?RFC;j2|ZwexyI8t7BI_?tw z8((=PJlZ|Ne}7+x0Q&g+g+U-`g=C6cxr+$t)uQ@$so%2*sAguq)!zKOeS7CZXnIoS zqCw^&%(r6bctRU6COplX`p-FrTHruMo5UW%(Xo8s+wOAkOUTdb**DVBR}peCUj-x* z1!Z@0uPZdWHWoMS_x6xyE%vY`DA)cTF^5-a~q><*<36Oz~Z zS|$#Lyz&8~8oM=yGB((l9S+@NkATXSQO{Tp$sXOS{ZJ49vbt^B$UYggPua;dZvamZbZkXh@hNXWuISxOhVK(#;vF)0^lz& zhVRWj{y7x<%$qPo#nZN5lYJjaU&_}Tl$L*#y;$t5$EsJcEC9tDe0R{jry2`IJ`w%& zx%cG2saDabJ{mz{=fH!8xuscOd#~jcd4I`+(|sL(x3*>%nS#PrR`d9An#(C2r+M%5 zZ$zARK`RO`@1f~u1LRJpqc7(Q2hIWE5*gw3wh!L_GV4@dk0CjH+=)B6X`Ey#7iaQ? zgx!@spNrV}LcPSMJ41VBP z8u3ENsi~;vU1U z`$6tHr)$)<-{HaKX}=4ezzubY;H~qKyXntZb*&A}3CyN1J3sn)a*JhsK)2cZ%vHFz z)9c8K$pY8Q@O)+a;;_*ov^{p!8&7hUpvFduf6iz5>Eo#$*o(d$b0Tm5Pa5tau4MkW zor>oAM)!>rb&YRuqWc0mcT1R3J-YLSt$W*UEuHOhk=$}QzV}K|C*+(Djk7+D$B34^ zojk7JqbHC>cSHkJJ+dgTZibKR;Znn7S?|m;hOXn!di%5AQ}Ek-aIoOptEj%tbCHt# z#rgcSfw+yVao4#1nqT5KNV1l>Pr z3xwx<0^3$@xQ!=SL$-4Y>fR)=BHOZ)^$5NXZ0vA*22G7l^fdADXtJs|=*c4|F8Aj| z&rKGp<&>?tSy;G%l4pHa(qMP{NhYgA*S689@?#76XdxH!S5(PtFV)|7hCoX5z^K{d zXDc^Bj}v)c^wcS|+*Zth(WTZ3A9BAsJ`5vKjMDX6nKE|rdG*1N*UH`Nny>h>=>*4C z-Oo0wlb71_C1szxV5a-SH^GNUS=(Eo>2l_%7W=drFJ169p+Wn}l zV`f8x(_A!-_)`044~|rV=sF2_u!Z`K8awWaCU+1{47cYsQt|RcNt+dYlkTeP&*kLE zTgU}4-aO_jcVfKOJuAg&9O{C`0WP72qv8FMcC3c5aILLHb(kLecpcP$RUyNyKk@-w z?oKC}j@RwCowpznDQTI?Eh%MRx$!%->%a@fk{LeV>D zRphGq$W!`dE~|j+fPZmDI%*t%ld*4V7IXjLi~KuTRxMOC5X-2h(w=s(xQ1JZh{ifS z0L9+(vkG_z5iYDK8h!D8EZA=KFO>9Hv$RDGG5l2&#V<*6{iSI{`T>>f2r+ppzZg@O zN3=I!Yo{z6TKaAOVwd}YbF3vR0Yvpg0lCI%$jY;X%Vnev9oG+8V1q2PZ&}o4ELqqxeaZAzZ4V^30<;N>Ss}QBoT1Kkp+(aj#7y zdpU*Q8bZGbElwGClhee{z4UOSW>|VPW@T^XXr7S}5CZ>0$|f_k@t-dNkf}F<0_m_j ztdAHCm)PjClmj5sKqb>0z)UT=JUjWwh$JLOPbrF5BNIXCx#}~3XX&<)D4BQ5;va}9 zE&e*Y1`LHKc`ndde|*C{b^~ zk+Bvc##p;ygogY5i#r|akifuV)G3EX84)+15e1?$6O#S*N96(f6nK61aT;!{*i7|j zT1+qktjnj&b)r`fH|EDxex{tvzpX^5UkRc1Vup67o2H2Tb+H?qcz14agjlJ2^!g47Q=E8bZ-aBf)8Q3e@#XX_vA9!*p0na1k`J}O&W z!R7gc$3l9m4^JODzmLCgsNdhkYZ2g7)g2kQAakyDLQk#S)2z=rT@lDDAYSAmolfLa z|0t2~rDMe>52eUQ^$nTL`}m^-d>TF#pFh~VwmvQOu6P0_@|~0d2xlErA;CXvD&V08 z-Bbjuik+W>=|T7tq+-D*yVhzYr1T>5bmn9F>l-vNs2s$XvP^&h@>C%J-V3v9k-BG zl}ZA2r-8R~^RZb83W=9QY&rp9k?N zQ}LG;0(L?&Xto)b9FjM(5xGm+lKg8mrgu7hl=zM%N(<)B!L!p)>N%8c*K)1z=H9o$ zv$PM1!TMRh?$AFSq!H!x6qeJ8r`KMxrpxwCTSo58W%KOqzIL609Cs=Dxt*HBG%FrN zp{a&?3Ik=`cjl5G`|Y)-6A#QkcNvYRb-q6?p+wvRaI1(ofLn!TRue&q*SXpyuQ2Vb zdLs?8(m$B?JJWh0xkyP2H!8Q`SFrD+t~Zit#>(>eK~#GUV`aL6>t=CT_J8A6`v(3S zx0-r5-cb>Uwl0JSQcF zjrN_S%vV>f$`dkEPgH#Bwxe%1w+NO6Wt!k%tkssNbs?X57tqxTqd^48&?67#_g|>d z;Mv&=>`GXjxh!Hd1q}{FA$M29Pm@OQaAaunLZ;wUNNz!Y3nbF=IE+R>KFuxG0&O)J z99~XRvV;DSk=NKg?zfM|n}V*357TWGes+ZjsE5EEn2;`oJ>M5aq#tX<()ZcU|J>OOjqhE-}MqVw!Q5dU|kW7AE!jv6*Gh~^if%ue|Fm?A2% zK2IogJHbSyC-;FnI?=V;F<%r7o@2F*cj6-kK^t^I^MKcGa5cmdlx+|abgy}Lc-DZz zZIU0!=ddP9CFMwILN3Vo31zqx9z%+75QIZUG^yYVU&4yNtvX;61#iv4O&bS$fC`cC zS5e5}M=3cE~blyphI{M0N}rj0P4ZS?NI+4M`!uLBcDxq zB>2Nz;%n7{(knjodX>9dWmpNOEA6U`VjS&TI9z+9{6fTDv*Kcn^<=@WR&D$|pSn5GO{?b?_)I@4hV#~AT)M=zZN3-<=2gmAz+ z1)P|nZ!6Dj;5~*k&EUj9I=Fsmefd5Ck8YE$o`H2C#e|6XJD^LP;_hc%b%qG5qCk6- z0!Rhua$rLB)YL0cIw#UqU14Mbw`fB3_YJzE?X$%6`}M~lHmVN?qcSO+p^#Wk3>W9x zk*Wo>f#dov)~d)d9skvYcdwWX{vr<{1H)e4F3#S(3v z=f%MXtzaUd*;OTqXZI7e3A;=gG-fa7!oNyfn zNo*LbQE60MGHlA$T$`P1s#lGWMy@)@5#w8wY0~gBD7+@5u%!&b__I8_b# z|IVpKg+P$oDb%l;J4tz6wL?08wWIwm=OT5J>*RU8!o)jF>+ zi8hjs8T+E|jn>nWqM0V!#24f+aiP&nUXq*E;WhjN#DTE27e9-oX=v8>Y%M>fqU(;6 zVigD1!Y7NlZCc9SpqrF4=1<1I!r|Pdt|roQD>m>D#~m4F@uuZ4&!!c&`m;UY%4-c= zd4WbPRYI6UHP~Fl>V-ybM3oa)eoSDg3)wOU8l1cwu8Ni3fB;(62OM}P%U~bqz0RH0 ze}n6csVs}kwr}Wxc5YgJN`7T3@|~2Z6j?`aqSc%OH2SEqb~U$Wmll*?v1SSwM=?6{ zT5Yz=sCo8ZNdo|&G8p?cqIsQE1p-V{v)Isc6I!EKjS?i;2EU*)H~+{uYN_dGg+2M` ziCxgH9^KyoNLwPT1IQ8-sPAo`xSZ-pncpqQk2ZAm@dmH``==`bCKl+GamBQ3P*p~U^G)PHEU)ZH8)_6%ip{Ahw2*wgh4|-O;)5^@=*H3>|GM)5Vl24TfYnF4_RCY=EbcQc2v%V%c&`|o0aq?(Ymd6f4WL?`-zf$-Q_w)g(?;Vg?CE`j($&byIzm3bDHOUGq(2 zsvhQkgI%&`B|0)Qh8>gPFJm_lSJE!9Y;Qc%&QrmggnZ{zw*sV2ZH{S-QPcJH=okNv zqDBETBNosPJB?QyUcTYHb)*rx+Wh-PH?{+4i}SBSe2;$z0v{lj&oq{7Pu+q@YgN|F zj0Oh)H*M)87aHpwk`lr3D~FN4bH2P3NU2Nxj190!YFS0~AXS)yf(4J}(XVHx!r1T&w}g?%X1>GK}3{=$~GH-c+JgLKr(N=d6DlnDS{-`y&q=4A2|sC=@q zg9BIk;t+WY+3a{iwo{`}Db&4AmU^r0lx_ImP*vb#1DVsJ9Q~rdvj@pT zKisRANR%ed_v9PYa8zEwtoZe}51m#oII5KV7jxKuM^g||>)T6Mm7W?3m5b<;@{ZV? zO{;oeYkCYoYufC_Y`~8u->Z?;Udd%>e8du83vFMYWe5#8iixR# z%g*_fUuuVh9hnIFxd9t1o{v2G^Omcj%4 z7d`x0FcZ_khk^EUkJZcPQ^x@(jPZ!|QFn6>$r{j-U$x>X3*+A_zwIqgJ1BLYOOsqm z-ZaPm7nJ#@7`=22NAzdv-DhD{&xS}=1~cggvlSF%gFD3N7ag?aKLx0tYl_*VBtwsL zXPh^mtR+WEe{?45n0Fp0dL_-SzG8jT3olN32JgLCKnKuy>ZwPQZbV!; zkQ5O?H{6Sifu-M4W^=;#kOn0I?;Q~0zJvkORP#1l`z4Kc{D*1@*H6)YCErB;s$OlOfUvK+BJ8UOp-aX`bP7--62MkJe^R7snzzJTdU5iqTZz6*ve^nI6uwDU zW45#Db3S{s79jmKu9k6v&=;5_|9CrABtKim=$`go`&!fT60wceJ{G|M}tqRuq;J$d1q!={7d+u?nsA7+vYJc@*>z5^qTCi1BK8z|qiz-E8{INcsU z5_Gy~WvVA^+UXj)1sH`^wF4@jS?03AOv~QMbqe!~W>o*q&Nl<|7KzTt`qm@0p{E$H z=h55*`r6hldt)g@lys^S4ob#NKQg(>0i~Q<-3(Fd%-0CJoMJc2vf5&BW#A`Qm6&Cy z>BbH{zojgO_lu$bEegm8C(u{WnEwL;btUIbOr@Du%*fwi%Z{MItvP(8f-t8KwH>qq z-B))JXz^Y}NQMe6$(7P(fx3>bBvlb2s60^+oyJ0`GXp^%AnZKj>bu43X0POLAY!C- zf8)PNrfV5t`i+&|erg08Y=SL3vnDv?6PVLh#|=RYc?V0U0s&pjFxo4!<@(TeaD;Ur zu4SYbA1**p1wQrmjOvm?^oWGk-{b1&$VY0Az(6B?Tb34Yj!S7mA(*l&Ds-gKuQU$Q zL61Ba!=Bu@o(yf!&$c2ngq8|n?viCaR`?V!pGs=cDCxKURc%Bftif+*blEzR=A@&_ z?`HDXX92&k*XR9@zC^b(U)E(aWL-`tB%l*{cl5s9qm?JiE?}s*25adt;(ZYNWAu2K z^*vjkY?Ye>>c%kPeJ_WPWb~WvrR_PI?$g4{9#7o+Ca-^V+rgUht;`3ll=|(zvW#&P zBo7bM;hho5j`dFyBR+%;uDFDV3LTDYQ_$}no7nSxMm*f1ge@;_i8$pIHnXU*dhT4+ z(#KZR8x#P%?&=3V;b=(j4Ouc(nZxTrxmRRFM?ON7Mb5$D^fQ8A3Tn6(3ce-tF^m*Raols&xl4U-A_NUh zHi#{bhzq0Ce5hk4N}(re&DVLH-0L1W_c_=Y@pw6O{;sW->g_w?P%jD;!jiy<73k#l zndocxgMKnn{tAxdue8q|TEZ%Wu=W+A<2bVtE$nC34#QV5s_B>{w z$3`MM49YwKE3-GWDAl+_fLc@ZOLo4?lZKcARjHP9=B!C0t(`_bN+BMZ>55$U?k9SCCI6| zt#B#gn(H7>818LJs}hyl?Y?BMpiX3OD2I^9t=p*DES6^7ZfFE<@o)qtb$;{{O=fSG z@iuIoqkYLw3oh(`{%yom{xk!;JW$+{4|T~*>y-`jmdtmc?oGp6?G5_dnV za#F@G{@bM6x8{HB3v~!~s{7^5a!jeHYuc9-c`%kAE>%t&_AAcaUS?j(XnYWD{et$0 zp`A86U((h;A&eWQ?6XlEuP zrd7&bMU&BRTFf3<4&)lbjq3e&;?U>QUWngCKtOfks1;p$Z}`X3CPk<;4=X(aTuO(( zP2t9$%+e|N-&ob1cfn$dAw+G*%RE?h;uZq-y%e`Bwd;b6il1J1B)ZN`4g=_0pJO`0X>{FsaltK^~nFjEC0s z9SN7*h_;MR03=#$5jQc10Vl~95Y1IFfb3Z}&ACk4@c_LI%io*!COGxtc zjQWy}R}j_$o%8u2_Bc$R&wa=Km&5VTYwg(4f6PHHf8Z;O{<%IkiKrtNl`5T}D0aRg zRC-Y^`Q|Cno6?^zPv+mLtDUBVB^%NT+usf^IiOn#u2*H+R^V^s``GbzA)~+5FvE?8 zrPE~X*XL@b&0xPyYEP3+zW2_u2>>at?@o`pjDLpx*h&bB2&^?{BVF^irJj5-{56PqI(Stha zLqg2S-|#;ua+;UBrKq3Rl%zl`a?+v9(Qdm8Xh1bK zYxXn6o)GII!%3hDe}w%Df=#4v>d6f*7XMTb!yB_R(gR0j6b>xn!u> z78G{d>O+rn?~p;UME&b)ow{@xiyH;Y7^MWAu+(aV)xsHtB}juego_%t0{8p}?~tRP zXzK+pKK-hDBWeP4s%xP5Cd@?MGK~>vbf|rtsIFH;mFuRWfK@fEZer8sbNL`dTo?T* zQ_@qEPi@25fVK$|1|6fOK%rsuQGV+^OF>KV%cq5(|3HdXCsFwyiD~HfkvCxu4Q><0 z-aVL<#@Xv18)RX4)tvHUUwav5blaf&A6XWmalP5=w250d_LLOp~EdT zVctvCNtlLkhuw45yU(~eQWkIQr0@l(GI0Ura_&6j$lcqTK)FdKwQhvGXL+^T{MPh- z^P7~5Jhx)*=@eHbT{m@w+S$T4I!+3qO%L>bU(~;Z{BixH-)MhH&3iyD|NQB5KCkG7 zDYl36a;wG+J-9Ze{#0bav89GKtCLSVK5Un0(>R*JpW#_4!%^`j3u#&jpY;?)*Z1(MTkL<}TCJ46@|>wy)43Smx$`kXrD^NCp>Ra2IdV6M z`83&uCp%bff3`ZRr+grs=rwAZXK^xCx1-NX{b*17%f}KS{>;I+$Ua?!l@C+v{kLqg zsDqk$@X!dI205VyO7`TT(-GK70kdzz^b-nN=Wl5}KrKvtw!2Ntk2K0@WiIpdiP#!yCe9jqDT7G5+>#Oxk?c9@Y9at@5v8OLv#}AiMv`C-KvR6ODbUt*`bd79@ zI)79zXlr*CKR!7zlTnxnD^YYV5*)GO?E0p=jX7;`sb&9~jWMTwMQC;%fqYS9_KPn> z^iFFVvlZ;_;qq=a6>^)3-#GIlIdXb3GCDm^cM*949fwA!Ij!Fy?^*Q$Du%BW$3aFx z5))mxrH@bvsMeh(G&y}fYSI}Y!C-SE}kfV-0Lf8-FnG_4<~Fatro-v)2L{>1ot`Sj2j^%rQf>}$9rj0=A8MWZJDtX$y6fp0DPOQ z&8P4{Aqh3wEK$mcNIELqcGxcJ34|o4)w^4k_>}}%7CC)*J~b|0;-zuH@cVk-D#f{e zq)?{4$%eB=2q+XR@l7qYL058mK2q&@=M9ryGBBv7;Ud4y(y2N5ZsD#K4Miq^Qh@IW1m26C5V>$uO6NJ)%k{L zLX*PP-=m@$GBaXc5PtS-leDk;d@IQgzg}5A420i8?T$jHjB+nz4wKWQb)E`y3<@L? zKq1`i=WAUbRl=JaZ;&5tZ zVa8eNo$d|&4EZHY4nJ0SH1bB8J9 zQ8{+lh|uUvS6MFk&8nZ}`s1cQEZhS%#XUET+iOb6VVd?~CQ)CdjK;Yw`aCPaVNwh} z_VoNa$@P+l4KO#4)|+b6(%ox)-KHT^3_a5t>)8wo`2@uNY$$bwf6=6kbA_S2bpydy)!^~7nRfhkY*_CFJw1P!cO$vHa}$yS?kKo zEipLDt@-<~H0?VFss&obbuKmDnb9`Hez3ZPNm_fMpM{RqohI{D>k|%ZAaqGjym(wq zyXEvN93_)@wJdvVYP9iSef|J`7xw_sea*KTtzQd83vKNAyxy%MLLi4?&B8DWjT`f| za@Sj7QThxLKC}AlB9{EluI>q$Q@YDY9n?X?j$Jl>ZH@&WULG>u9{YJ}KJg0N1>*aX z;LBFdkM0%yOOM-w*l@MT zndxh;QP5%*&7Dhgtw)mxZ)fh9YmYfsnz)1P!Tl$8H}>0~{@vOElO;rirMo~jo9Mv# zL%Ew9E%1NV0GfX#^)7bx|4>gYW(jhISrZj9;qjDwo(RSHu)n}hlP}K*{ogdcBH+M` zUC(8jyvPX zLZrp&SMdQcH*GQ*64_O zH`hPyszV{nZEGIC)(fc$Q)IGd)KYmuiC3Y{Tz0eR) z2dUrnVE_TP;>yaFiU=EX-~o0;*moJK!(4qLr_@U&F|AzGBKIQ{UwvTMeae-LpFD%L zz5l26_gE~(yD;Ww({VGsr7K)J;Xfm%hCne%5QxZH`)6jo0!Sgkz=-eTP<7r6EuKh+ z!2D-Jok9#0QP$OxSDwsPqH4e%_#5?Piu99DC!Kz2Fez8@L0{8{>?g|`NXP$mkxXMZ8=v?2L+ zFI^>->_~k5Ps8{B>o$8nNoq`^BEB%E66KUh?pr( z?F-k$|5ZnSt_P6nv4!qN^sJl^+8RZ$A{j2t5PMc4hT@`Zn-OCmR~s-N%qi>qeVci8 ziQ3a~VgCPNR^k8p zd?iEx|30;2#Nq*AlYpL5UZBbs0}{U(<0yi0>CoOLK1IwIvKk zL%8$bf9EXzY4B+Ks^9qkbvZpEL;5>!L->*98AxS#|5qv#qfF$v#zVk?;(tj>JP#AX zm>#Attk`B6&_n_CS_q7&=Okso)N6$rKL=MO%Uf5y1+pT~%Y-XA^gcVAdJJNEvl9Yxg1779TwOC`mHYP+2> znJ5i>$9wYG${+?%z8^^zt1LGeyslJN9#o^E{Sq%ZV_#rM1ei^@xA&)(97`)-q(!{ujO>Ily*?WbpknSLZp`IGMBrC}z}M>uuK(Es2gpq5fUvwT z^i3qGH>7&M96yNa$_0$_u$AWtREmEk8D5%C{wUGHoD8!);>uVs!|&p-22wD8?9D-; zt94I&OA;p06>TVRbjB0@`~#1@mus5X&^@fuK47W)S9)TcqO1u#W=`EnQ~8sbeu54!mTNKKTE z9^0yn%5b5YGxx(T;a$Fl)~kz_E8W^5S7y!k5atC5>NQ4XZ-gx^zN`|pAREio;3W9d zM`0o!QkkvmP5XzH<$y77%w^eJ>1wer5fD3XU-_|95n!3eALhgOwqN*rpK1PX8ZS>o zWeVHS|}bUNO4Xe-!q_)6b9 zdEKSRbK?&Tt^w%LmjZL&j|k!i&9)f6e5Kw?h0))Ag6r?La-AX8VCBl?LZUOXPp~@u zK7MSZza}eApJ0SOc=?-}f@AEB_w!PIimxoZ&+3>vf5+Lrj;oi-r(&nzJ+-Fk;LFw! zBk2eSeQ=b$!#o6pVZzVO4gbWu+i^C~`;xfLZk4>7c{FD)@wO)YVSUFwD|Yr9gL5Im z4Azj2WY0H)n8@FyLcS}7f{vmO3h?v9gOcx^Jh|6L_(&F?m;y`FaT|cVDbf3DC9-WF zB5;$a!=7Y-?T^BNqC`>&R|~I=I@=|3Qk@gneZ()7rkmV$`9D>cRPoxJ=hhx;Vbnqq zXd=^wpv*?qa+Sn_%-Zv?e zcyrz(Pi((1y7MlF2xZcU1u1>z);DetO(Gvcm6i%UQjiO1kxG4NAWla03H;;bvZXr0 zyj9}Xafd)6A+tGIa<|~9;xwPa%yUti&_X}!`=$}Vxsus{ws_e2i>|(n^6Pt9HrK7B zL}T!FKCo9A%~)R-;#Y}4EhQ?0Qp5niRqe{rccfjdnKloxMca^-;X9;8JmLR~@ zAm`?l7?`2(E7@ojb;897#BPK3!Ydaf49HsMdL-f)q=YSdK@VJ`j_cq&*%P_i-GlhE zC!WdwaP)0&F!-@DUo+!85`@`Z%;-q9$Am8gz6#`Rs@Zgdn6s2A@>1`OX;>I2A>8`Y zDc(cb43@81yKu`cox6NWQ;nNWBb8Nq4Q^T4SC71wtI}-i4Pn#c{G_0tg5yxC$G4b0 z(NW(~|6TFDAvsdtZdlnuWK;8%t_$2!sXf`55OCkB*twXU_A6^X3skJsK2%^Kc%?s` zH&d&aAYr)N$F6M?&h~JD-f-d?oUi@OT~5t!I1sNLh0*ukj3)#6BOh`)+ETpVd{1FO zbwDiK_?$nd1x3`?W@Qn~5{P-1-tLronEUNRrsRd%ab26qlxOl{D7BQ7d57|Nn!g^g zWt8O4y4$Cs>Ld148WqC#=t9YuJ3nVcB%TJDx`aXL4Jbx>8ybaM|zxo_&2K& z>T>avYqxl747pV!i4O>Wt(1?~HWmUe3XZr(KpSc!(EeY>zH6DNmhIvGGr=yq*7WGp zZTYMeX9g(r#Ovp-m(Q5m0@opRxYy#8($6|Yjb{Sx8TwDm?cg@AkwQuJ!!|55M|9U; zZQS@{^^0;pN)(fQd|3E<<5dacQikYPFmkX*)Lo;Fvg=av0>}+IqDs9U5<(ZX~P26AdQiZKbvPS~ep*pD)33SCgX86l*2sOqX7UNXY#@2j82>rF(t6~_! zgSZ4b22Md|e;NM11djO-Q7hXY)77Q@rq6k@optaBv6ovhnEhX0KE8>|WLA)#rC8K6 zG+(A{-Ptsxh+OqE(rPcwMJT*|@c3pYhU$dkdIuxy!V1fr^Mcm(L3H5(zf(`xyR~7v zpnEeYzEAqyeVoQ@ zKnlozL?4j;oT5$W{r%f7nEac;xj;YcTjzCSOqPKHTNNb)N);R`6Vol8t2@c-){7IV zSTpX~FRwEGVVg>l5TO455%wMqO>FD;w*pG^d-zxA8=tebBa@K;-CC>VVf{=&-ZowEEa--vF~~agiNC( zlC9za`tK?sVpkm@iTu8e+wgK1ylH$O==oB1^@UdD(|lP4=zOzddr|g7LNcQh*n>@% zI7$L5@Ah|M69F`ar?G1v6aNDYjPj3tUQQwQ-{xzRH0ri9Z=mDeH;W;cr0uZuj%8W6 z1m({Wi3ktqW!p3pq3Y*pDfg5FipH9vYdMUW=2`}QW{F^{r+p_ReW{A1En_TySg;TH zbDJdaUhgHt@qORMfuT4osPf=j%bn|3?aWNF)JpH(`cjEhup*QoyeeQL>pza z>_WK*xWkPVs)Ks!C*Bgi@b?Bt*`~ly8g&shSH=0T-mwjN6%xSCvi&wB7xW6&knUMe zDvx4`f5&FtZO(0mxnc*dF6bRYRzUW6C$(ziJ&&(O9>2n>)MZX9n7v_yL+9fj4bB&k z!E_}14;U}#Kg@a~-)GJ5Yr=hyD=oti%54k;H=2L(!^%eWW-|Dv3~Cp4hb|pyU~WhP z1oq*Zawl(mOi7r6zRuf&Qy5|JkaDW6b2Ib8+@XuMNh-iN9u(|&fN+7Pte-o_2N`nX zLNl@6nie9#+74W{3toi?$e|!ut6Crrl>0?ZuDi{a4&TWyS~$hb=6Ip&EuZpJY3qiU ztTV%)I6kzAe?owIgE7vGs|+jMNtj8<=^aTSn(tNGK82P`93cDQ9%KJF9OYTkx8n6G z9|h=1m+Y2fA%?0Zr4xaNp&U{H4`gl}Dyf91xRd1+zZaoYe?6wGg@VHGRl94bZZ|l(&7@RUbV9|GkL zGD8$(_7<7jb*<}kv(ys{FHrkA60bewe*xdg>6lz2z{Fjn2$ioFM@W`i!AFK>y`1VK zN>&vG1X!Fu18>#vKyu)%>J7Hg3SVFi{+1-y`#`W#pQ0!QHXUzW1InG+7h%G?^ZL(e zuJ+N#6_g@NJk1hjp85L1p5pp;;EUYg+iHlfb-5xyixjKGOhz8YRY=9wqH%qw82Dyj zo|3#d(?4#!ylrNXK3;!#65B*bT6TLnaQ_a&Xb{svq$vl2b^z!T4EEcYP^t#&7Se-* z$)j(y)wyL$Bu`71EfcII2`2a83YP&_Y*~_h?qliKiF};^YF0>mdH?l`8Itnp<_(pm zdWP|l>(xZ!P(`yUR`|=o)#y23+V8baPc3KOIldSPXxglgcb+FXQ^=SbQN zaY-06d8Hqj-5ndV{L&X2kkIxqzm(cWZe?9>zOpd-D2LCoThC9lTC8ULK&r{pP0rSkFCd*#PL=&B(n}+U3q$CLh z*|Pb|ccnWMa$!i%T!76?_x$EZU(2$05;=S|x6xX+G_{-R^z)`4O^W|`ayMFf`_ig* z4p(=JXF6q3W!hnhcm3cm@)Y^&wRzyD(!0*DaiCdD&~??)M^mMiY{IQ;&O(vf$eTGR z(YSLau{>|l0I4c*oBwIFq8m#+bD-&yS)( z>5Rvfm)u+wh449%4fdLdb{WQ;V81H0xK1bM`@!}S(_dp)IWfK`-!kCU-t|~ z))miDd)#zMr?O*7dBjT_NxYC;9Yc=r_$yTrP7|>rmaa&Zk^b#jp%(X6<H5ugJag)Te6c`P|Di z1VA%3zavJ1U`=1jkG{zwRIZTOe>A~5!}91$u{$C=7}bydUZzU-{q3*(tRzNM+*(dg z$9$Q9?f1J*LUAth_%e@=Eu%Hk(mLbwH>G>f7;WX0>n_Aa{v2+m;kBq_@>CV{YECtM zaHNDI=d*)ey;wLP*S>8S?svBU;@b|ww@RHCKf z0%i5PpN78Wjif6x&#$SlVm81!rO5{3faBBxEtf(4zi+pbAk_LahbEtdhAnf*M|Ja4Kc*c32d zI20;ema@5)?ec07giv7A!O!f=nw6yWc?ziuH}urc?%t!p?2RzWqyZP*%fx)nf8K`0 z3}Wr0td$@f*u5dvT!e=K;<3xQc&vsvTnv|RQS9kjI0RTin1_1S7I^Z2ZZD3U=8o$n zG30ni%;!i>zMTChv)bt@v{W1B$ja5&d{*{T1`lfwq{$!h&b-3d2q7=vs~l=G5DSNo zP7JW2koCTZ*Qvh7PWqn8(t_W~XZ(INd*-8o+4S*zHr>H`w>N^Y-VNfIieE}oq^CLP zhPFG0WBjPSlF!QG&V0ajV5i}_D2td9Eg3+pE&@>6CWJeGLlGy`xqK7*-5?=*eyw;B z3V2JPy<%!)F040vhyIFmU6r5~S$|q}jhIe&m;{dhcqpcE2Y7B}rfas-nE=|isytWG zbLG2jf1@u02SU|r0nKY3R|YnXs#qHVztCF@#L5k*1$8Cl#P*2nM0^Y~7yf@T&*#L= zd|Re<->klt_p+4>++B8G9jl%?KGu)bXkG|aDvX}!m&U7!RkPwT6(;VyEbm|@7(Gq5=a?o0jTAN7hAVQXwqqNjDLY@ z-MKP>A~D~!2=Iw}vT_Uf`iz@o(Hf- zcrrA(+5YaII0mTOsDm_lR7=peVvy$}ZLt|~RYTw`jTV7UKa!5TF z4L~H($>GXXqO$I&(1(-_J^( zyHc9z;0)(#v~F+Q#k;we(-zTZZs`-Z!As@1%AXJ5X8e}i;ZjKePJaSWP;)EL3RON$ zu{b(K29&A~smG$3SQ|ba{W?|t*Z0uDgS_|!gP6a!|NLg@_==RCXs6O)#`SFb%kL6( zcU&o9)L0AxsTpm*nK36a?T-W=k+Jh?-Z`YEfDYm)35pjlk^yc*4w?CPUJr}+Y6`-t z^VW<(bCDcwQV+YhfV9u&=NIez_=Rwh(yqN6{I<@eOrV7H{nvZege`rB?%@P^u1`GD z>XUx2CgFS~UJoOG0)zNX0QzqA`SQ_Fhjaxqs`2N@tJHMaB>#QUowBWu=XfCnE}N=k zWxQYNl^?6}z$#Y`ta86GJnvh>k`LuQ0<4uP-*|I{xC!20c+dE9OP{h`h*qBK{sRMz zX}^Ljxab?;zs7<8s@TCwKY9=2xVu~$v|m0S0qCp4U6L5SAGU1yG5BrADOzCl(PB0^ zWtq3}j}ZmSaWR(7Mf%juTUU8g)O&gF3F*9CURq@MbROvDHEmNwhr)BF)1SA*s05R&JkXsyx9fI-$zTsG4brcl0+F!gY^tWc;TgB|j;mb~w z@1?_mP?z#7(8XXBCjdaY(*IX)O2GUx>(v3;*?dnmy9ae`L*}r_KPku6w1HEXZjlli zYnsq9l_s(hd+>Dk`Q^90DR#8{NeW|RWW4L2wMk|hu4jUyc3O?NET zl{PPD9W7^PUMIINY{}e|#ns2(>3EMP>6fR(>4#7|sWthRPL+Gx&s#f$$G5Hhp3LQd zYU~$XN;gw_#~$H~+ZS!KdnUJd(VnoynifscGr!S@9|nue11vPqwCapW)Wz5cc>r>p z3WRjExYg%<7xXP+pLJhux6-0zLER>~XQ%_#&)W53nn`ja2gR55CYG6*RmI!=GJG5~ zHT?WnB3XDUdPARPlqq@Vf4nRKhCdvEqF{nlJNdK`8$rbZJq?}`>69<)zkk8MX z7Lap%m`LSZb2Yk6UGv1UCRV%)+{!h~)LrxmG9#JF8}owQ&U%J76cWqFYz+=kZB9Hk zZ;h2MXYwZUzN`$&{nh^&maq5vDT|L*r&Z0j%e=oS#~U%}U6*w7ye3=dG{|&Y7-q`P zDaVf(`H**t?mo_>)@&!^navB$m59}B_! zrW*g3-~8jp`4ae&GREAK`Q4`7Z?16-A6GXnNUU%tbiua)grTAD8$mY2{uooJmF8!R zv;Uq>_Xf_T5wih=yxAmMOZ4STUA24n_7)I0WFXWWh0jWvO=7Gz$h?l}PDwT1dzZ|6=n|nEtzQQJ z@t_4D8V>_RfHwfa6?JZmnK?kQM+h-uzfOEmZUYx4%WXHqdRJO<=;+n z8N1Q|Bdl}~>}@9h#h90IUJQwI0j(ErA){lFSOZASw)QO?_~qMPA9CVBy&^gM_UTx} zIkvbecSz$vjcVw*K8&t<(=A#;U0#c6)eB-QPz`%mx z4zJ5o2X|Y{;v{z4C2JolHA(fY6KzD7vSs$t-M}kj&Y>JlLK%GTf4jm_h$OGoD@AAo zm4Aly?U_%YwsT~$I^=!PAV>J>9dtxU+E_>wgQ?*nsF&{X&;Wsu=lMQ$Is=+odwcykZ_ zE@0xmlR2cyG0oVa=>GI>qL^R4_iqUpnUJ5tlTRe|%xU)GS^v$pO)U!f?ytvAIPfD1 ztGXPqt5C%O`7d_Pv{g3HF*1aZFf%g$Diwp_QX3e_n~@MY0|-BoR()FM3m? zv0CBuzWy`q*dB26g8(i{K71&v)3TSM<3e_JDeG)uN{rg|R=u0;?J5jh6XWkl)Xfm{ zm@XKax?`1agsSsEPAtMooH{?i@YSC)kpVWi4)J`?ko%GPwD68GW;3R8sr4<2{bSDkHHYY437w)2( zdN(FZT27Pj$sZQ%1zVv^7Au=ue7SB&Z{Is|a2bG|;$=L1vuY1~VtC;iGT*m0&pm)= zS61la_$k)Gj$AUo#JIG0M-h4R(r1!TuOJ;>J-n%|Sffa-^bcL1ZTM#1ZHLXb-bq}sNpfx6;QR;w@kNy{dxTO81LCg;s-yfxeP7YVI|HENj=BX>$G5@RfeK|-i zrj_xUSA@Q&rcPc_p}+dRE07E&Mfz4ER(mGauGqu9d+Jx?^J&ztCF{p*)4SbGCAfyG!Ize6U636zKC zwjQ>Hq+>;-MI7u9upL*|`dr&L&s&)9P~_Qp5-4@PIwua-(fmamj&k`ba#I$Yq@4M2 znr1QyC!ITK9g^o6U*x`o1oH1TXJ2?qku4WT=HGdv zRT%;JqtzQ{KMPHkVF#>8DKVl|&&48~I#si}`je0{ZCMqBUdoG6S=HEq^P5s}IzRGl z>Va-*5Z z$CZq^P%hzhOd&=Rkw%{vl>ItD$~uSQ^(z}2O36O524gv(C62AMH4-f2lG|k`2o)_* z5GDMyRt~Bl9WKW#@F^!iu1rsWSGgV(qSLI#G>7Xe}{8 zG0Dpw>|_95m{Q$y`5Z6&u?&tJA7e68<{Dkq>IQXqV_)7B#puTn($`!riH~8~%biZC zrQu1RW!hJRI<=0Qoz~LimU-shBufrhUdz7(DQ*3XG=L-8wO+T+z_B2r{s7jk8vw&q z|IIivli^pFTz!G8FI|tVg;yV1zk(;L@JU!<^=gGwz8}2tf`}$s1q>=}Xv@wE(Kv;V z=%_5Ws6rZmVZBlnR<3hlf7U++2`jr3(O)=tn925KZrm~qHU~B{W79F$oszCJ^UC<) z8D1(aQ`^d-6}wMJHI+uY(AoxeS*U%s{);fjKIheI(A_?{OVHUE%Z2t0))R$IzLUGn z!&4H)r7U<*TT8~}n%+(LCS8mAIQwW$MWU&<<9;{k@rR0Nl+ASz)ky0d6@6uKws<0G z0U=snt^M|krQyyl{+?4MRiw)AJOeCwp*H)%kJ_aC+hR|6e4jvmK?vB_O|{-YLK(Yu zp=qg9DW;#|9h^JJUPhQLFz3d4TOCB5bSovV-pX6q=9}+sOW;O%5EsHXrp!8L-o87X zKWwbtbMj=RUnyT&9^0JDDE>@)G)kAH%7eqTH^oPznng1tDtOI0EoEdHB2`^Jgo4-8 zpPHa`53s5#qwcS@3+v2oQP-)C<>0^9obnA;M%+<3M+mQBt(3+JN+d;htWBU|A8hm?XVuyRL?m>5u9B=@O?Yu%WcsGrpcCL$9^8JoKjvWer(0Q` z11(eBt-)Dp2yAqS&C0NfJ;%p1Uh<+VYIE~J3K6XA-{{P*K=D=Vt7~6hN*;4^)`D@Y zu`IBKwpI%F#L*3bh;jDLhkrPg<3$PDsv`c2A3RE~JoX}GaK-p%@_}$s_D}MDdDE*j zpbR6CTZ#RbVOZ&HC(f{@e#~>5^@CfAu*n;+JaIyKA6tR>&WsGiGS(O5(4W35=F^pxIad(b!SyJcv zf!4!6(ST~ybRn^!s7m(vs)>3Db$*`R6i|@&c*cte+@6{mv`E5Punz^lqK^nhUSeQ7 zaVqZRQa>6?cOQFoJ*eY0@9mkd^(>D4ca%oz-K;&j7n;iaDVpWE9A@ELrAuaIt+i!c z#u=YH6)LGqXN#^bJIo4368<+ImS&vO|dXbhaJ}K$gk5J;`DDivgTi}PwxR- z#(&{~J6VI4uQ54Invd9u^q9!K9*s2Kyid1V=4lXy++}HlMh|$)0pHK=%hyxP)T$Lx z2FsDCg+o@=GE;7a4&%7g?vH_spJsx}a)$mc{VbFI@vC#ftp3dZHrxF-r}m#R**|Ev z|A3JEgPHqJM8$uTcmD}V{RhAIug_ONLpTqu`v=SQpN7MK;d1+&)IOi)56Sv;&z+d6 z-+n%9;XiB(ouB=AfPR{BV$wDmXR;&!9Ci9XjvC-3DA%`r$9)lWeXmh=#yh|0$}GY* zaK?sBvhbzdd^UgDK^6O&(jBKrK%t;G&yxSwm=^N0nzRnT`3)>YKAPqt8HjI_sCD0I z=@6TIEu6iTpq959+*T`=0cknU^E-Fh{dtlQwI?~-yMEgXcv6Jc=KvdGk-Yl#kN1=P zKX)o{k%zHGjr{F){&|&eTn8DeBRI58bPg1;>4sbboc_b_QRecWx;1QWN_~_6Tg^a< zwEskr`f||mh$~TmtKhmYjvz1nraJlrX2=jYXH)AGWU~4?{@R#Ure_@_!D%nu>tWl- zxup(pZil*uPR znY0OXJUC8Q;M$TbYnk*j?S%^z0!KSnW&i|B&RyIdo7*^-YoiM4yD)XpdyKm1z~{08 z;|k#NQ8P??IX(fcB51!?SdO-IR9F{%ZQRPbm2bh^R?C?J!OgM{C!Alp`}Db4dbo*4 zA^Q)8YVl;{RH8dp!>tivaH1yx4pvz}1nQcbhtKF8i^cElr&gZIBc9WLlh6QbuvTfn zOwm#E&yJa-GeMDKIM)*wS3#N#m~tM?hes6y0X1E9g_Z?N^G*Lt^hzUvIcVd&RgU#_ zW33->biQi!WMw5|)I^Zy1D!?BjH)g=_xrH=4fEG|`THn)l65WE~;qm9vc&2KT7KkNhZQC^&W8Qrzf z%~N(739C29K0Ywu1eh%pf3F)! zk;0s5eNJMtMYFBQGqggRRr84zeXj>_)GU{#4@M9y*|!Ivkg$47OmgbDhc5m+E;9XZ z#UH71iQwrdfy)<`xd3kRZ?MN-q>nfEIUZlW;WgLkzPmg;HCFA_e6TeisqtKHSCCSr zGSn}$YNy*?li}4`&q>IVM$W4|(b<8XqQ zdUaesmALqa&pJ_@BSI@HU_P6;x#$rWg{+YFj&*eYN$qMNJhE@5bXiO7^LFsBN2nL? zb`^YBh8ZkU^7KKdUA0Ea>5Rflu z%uEZ2JPQ*klzX>2|`MdXllt=nga6*97 zHWyNYPfuROpm2ce+6aj83-e8VB1h3AZdWqr)+lL+xWP3gYAYV^^I*7U{VP5|*P3Xi zN~%Va|5xjQYvEhp=vIF21OplGbpt7`^vuMPgYBiD>6noVSi0%2S0rdNdS*g9K5g|X z_yte_px~?vIkyU11n*e0-4<_z#H@2{n2H1Q%3Rn8w(y-PH`@|i5sTfu2YwQ;P+bYM zY+)HTpyr8sd7)Ek4}(W6}$VfTN4AzTzb0#!L=& z#7e?X#o7p>g*jUUTg1*q(E`a_aZ!W$0Vl_JG!EoPARGQIuHNqs>-=MZMfU9&fYg!t zOgPuZ@qw8+TJ^ToH~NYgELI?$j)82TL%iVyLvG3Y=})D3aUS?x*-IB`LW24)$njmk zg@eCdqP6GFlLIg{VDy3QGbK3d@K`sdENh*TGS<}4D##Am8Rdn7JMlhG4t70A4H!QR zqnm4PKTo%K2vJUtJ}@(0I@4ca-uQr<2lUaa{16gYOxw9I`h143m4fxQy|Y$wYAe@R z+oPD$boE$LjQnLJ`<&OJ%ocQm}G=~fSG&{X}3c=2nchtjvX6Ekj*Kxff-fPGZ*lP>R!`)x^jylJn$Evys9FS zFaA>+bDQMlY2FjCJmb5TcdhTWeq40oa?$8qwPq#jDM@c4Z0s`WWRR-Ja`vLI4oaCu zpL~$M{VfrWnz_OVL-oIM<5;$C4;%B_8p)D4**)9bzmwOxtB@mcayZ;Zg?6;@ zszdtPUlK-Or9kOZqv$fU<9LlKtj1gX`P*{u9P}#+@WrGT{ zxaSEZ8m8LI^syks!_)N}DH`rCHbZZX)mbeVZ$|k&2o4Via-|{p$0t+Qtpywvfh0yvjLT3RIB zh->$yQ6|bM@{r=q}RQ8a+i}zD*Kf68|(5I>e8h0tIncvR^;x_f<-Lt zn`u<~%*AX-5&>ppj?C^fJnSj{C0*wmjXa3`MccH#3oRZxDKKH3YI2$xQ6C<}NS5y{ zWozR!S}FOrKMJX>v48akHQeS$Y28%!#8=seCu z(Klj_h2FW}M*db}cO}a|Cb}_Z(agQ&M%ldV8L|34qBrL|*q18c+$&FxPvV1Zvi%K( zp`-sV6h;}aRJP%I4LAVn?Y}Ajw3h};&Ii{G?{K1Q1Zngs-0cvQbrul#1(Dz4!yL=l z+|@RB%6QF|OC;rxp5UV&motVU_4_8Fwk++hbMVq}=kiZ>$%wwmtCU1(EDyDnS!_L` z!Ql%mtdX%C@_s6qqV^8_p{P8D^{^PtQfz-M>Uw zIg<)FRvJ_X+jjt_Y&%ZR1z1Y|5G<+Fyc&s>WyIlL?Q-+Od~%5Z3pv!ehUsl&%HWu{ z1k(+#*O!stR`=CG*hi8|B1K`_zIAmTtsjIBkk@*JgphA!+(4g#;u;FzvZ|9z&CjKh z^d}P)7x|nlXd9v=>Q6o=03a(o`HZRn1?$?`!lO7BzDpM&OM*CT6$w9>NOilDa zyZ3f2YXRqx9odIo!Lr$I*^gA+MLz~Ef)bgVpE1a2>EuPasFJ~3$P2$d{oY4fj|^(D z4TMF=bwI6P(LmTn56D#2gNL5{F;dSn9=7Zcm|TXw>d}-;;c#N5>eBh$kcMPUa{dOw zefL)pfJlpt7`@7UL&vD4qP9e&Gp&DPv#Xgd()&Kzu@kW8%Yq9Y_mk=TNv?3wuric! z$(W-MI3J*MVMdSw@Y9JoPG4#Kg3HJW9Ac&(8=;C)oK`S?sDj zR0+Ct+1_X1Gx^zmQ(8N9MItH+Ry`Hco*-){nGD-=zFJoG?FuB5 z%JqFQZ88uC_nbtVopnsQMOqXF=T$IGLzj(OOUmDS8$Ir_Y= z0?)u=@~H=`VL`^F-@*qU$m8iu zJp|ZB2i_m&-xB4&U3N~b0PU-dudc?oeIJ*1Js`DwAfkE~ZY~Ye5veTiS1Af=S-iD& zE*b*C(ooDuMER-H(OROr(`M9h$}SI|O}P>*nm38sIxoFz*7lHH_uUk+{~x#tF%SLy zyJ~cq)@S!>u8f7J=U#q$vUnGM&y-}j3VZXp^0nnRLT%2z<@uU7s{Khp1Q zv1%`RV=s#Q6+RTc=HO?RpWYo$s(;$L5R}MhsA^zwXlpOTdUDq!A1_@&q#__xohTu* z!mao=5tRjwrm%Jq+%!p&`42(`p=rA~A3v4M5gLG%$k{$QW13G?y!mFi^tdHNKnJq= zip4XS_29X%uG(@SP@0#c!$^)d{WKUw_luhx-PGQf*-syhv~QOY=+tMw$L)cTT%=~Y z0A#~${OUy0Kw@!O7n}e$RpI;t#uN=87miDIEI>Gd+^CoEhaR_9M}dzvr0_;$gc6Hw zcl76J0OIh%Y7=tS)kCq*j_TOsOsC0xwURTg)PQl&dSelCioJ8U<-!-zFUC)`53~t_ z;8d7t+zqly*5ykhM;fg)#JCxF^$F@g)bD@DiI9 z#3EqcnrdR|Q$4VcW|tWJc>1Hz5@9B@F9O&MQk*p7W|>)6N58U&15z&rtj-(@f}OZ_ z_K_5-ExBm31N-Qx=rW>6*i4ojUXD2EF}XWAt_oDG)O0g0UY@+r8#4)KYmg2nFrF(0 zjpC4C-H@$3bvJ+G@(mj;AL|_eeycB1wj6Kh$N+5lYriEENu33fnD2 zm_!T$DMT7yQC$Y+LyW-tpr03dk7@q=UFUez(&rA@y*IV1el5Q5y#Ve7C@ZUY#()LW zjk2`*rUM@DrT#@N;}7J;J;16xzXi25tyGn*Hc$bmWtZJKg^i*sBvT)(OvvQyO zt7fE`UQ5oJ%A!5#{BaVTH;uD;QZzE)>%BmE?i@bxm9Y6uNKTCOwG6cTU%_!8R#!&T zV{fPQ_nCAlvJ-LS{iCVgu!Bc!+0e?3k98|uq7!2g*JOhgDtlrzj+B7dI4dysx4UjD z9NIJ1J|PP-KGUiE-Q|7@vDB1?X%YZ{TgSmKW>&7RNJ90^{Qe{X70gqHL2U5)9X1rk}{faYWC*@-EHlnjL3kqB= z2kw8foiYYm-9rdfMxk7jxJ;6%x%w5e`Mlfv+5>@;cUCnaPKD6}v1&60SS>Ox7<8s* zL;SVrt@PAtlEL8dgS==vvFmM$k-dj|0J(wq50MK*@FF_XN|heATZ+@&*XD)N&OLGJ z|C%;QiI-C{YK`6DfzCr`e%J?eLnuK@xT&ClW_|h>Gex%?eo6pt(a>`Tq!&VK$xaLC zSI<{RuZAx7AHeQ^W^4EGegH;F#J=7)z-TU5dHlbzv;`zEl&(m4%|`3DxBSn(gAqc_ zIwrb%YgH0Hi1$tu=$c5u`r}fu;24hI{~6$i_UJ4v}K1^-j^2IRv1SgW%> zuv6Y#hADK3)=VIGB_8N+&;AAvXe8vVee@vsyTJeYU4LxoFFBjgqe%R;L9GxM?ATS( zCpy0Zd=vd)#k9RHfH>EtNLy|`o3h*DY;;;l;9Q{EK4;7V3Qs(!OZx{#1Tz9OCqvhM z{%ShD9~rHFP8A_3{KV^HVXI~=LolB$ls^20eNE(c0WlzGgU$u*G*Xx`gqletb`T~K z6gD&fo#O3WiPU)MSP|oiSY+&1(9Uu>2Vme7Q`7#Juq{KMOOskE`qoo;gW704o^8$P zcD^ZeE4hhHi!)nBRZiULO@_{Y*wX%`>wn6{f*AYUZElEUu@)?>JlbJfuEh_^urO$UG6u!#rf-5!_YdCIa4lB50Q>YDfJ^Bq+1Ds10}iaG#>V~ zG-x0F08k^xq=CO-T#SMH|2r4u`w$D46*~|hEz-Z#41d37+b!R z|Hoqp9C&+9{RE2{U8}8@{y#w{qg05)6bp2S(udmkdqbx^GoXyZ=3Ud1m^*JH2|?w9a{?3b#B?3W*?UK1e91G zVW^vBdvR0hVBcsqkORs=Fs=sxvZ?TOWp~Dq4!X|*Pu8L+nR3gA)&tCmH7BbM4Ni+5 zQ4aQb$S5109p$Jsv7x9igIVdRgU@OuR!BXH&u)|gly^opi{d5j>IR8=XZoCy^wkLu z#QU5HHWXui#Z-D~h2Ols*Z-<24AB>m!wSl`TTNFj9ka&SP?w7SfBovG;SNvAw`U4m zMa%WpC~;wiwI$sU#X=ddJQr)yBGRL72~lkT1r}nH^M&{kKyN=Hj?Pf_n_HP$Q3-O` z|21lasf=MYno$`lhOL)d9jrU`Py!9%pPKPZV$xrM)sbJ~6}^W==X24+$6KX>bplr& z{eI(&{EpYFzglaq^oh~78r!(J|Du_R^WfVQ5VJQQ_I~v#@4so#`5C1|a5o{Y!M=O; zs%X_Dg0kY%z03?yE?1~`ADry*1*)6xJ@9|%yZ*sz3wEf)r`))${W<{ojG8V{8gNo8 zO`4L9@Ub|w`u&!s^uurZ9(yqlLg(ld~mL{X$q3 zxCAVM*b%AM`?{|54A~pJ`%U-NroHAP9ktSTGYA(FIq~atDO4*#BC+cm`y6W(eyQ&& zq&5Df`dZ7id67V3@QhEQ)`K|DOfy733kKQ#U#hPRQ?BfIov*P6x3XmLS-V^4hOrHS z9!){puGk6piYeLS{gjLA8%mgV&Bwlr=~#mX6FsH3)9Xcdj#9XB*NCodF&W0_lRJO7 zmV6!L%_^APDK1>$t8f9W=H2$8iZODA-K*&;d`ju2S?h!2x`rNBbx4Cr;*khk3Eo^nsOb_&ZDLc?X3Ofh} zDH4A8NC5Det##0_0UenOCi&I}KU%Ur6E7s0!Nhq6nUbpA2D`sr41;)BIS8ElW<~r` z%gmMgQNr4sslOtn7g8efyJ&x|>Yp^Qi%Yup3Wnv+p^>vpjF%KDSZW{_GegGqD0NX5Yb{urB`JAfT%51cfi#c z(3uHhgdL&*6PcSpVNPEirM?=>GfKrCicWk$(}a3bl@q0eKjOjg-Mugo1a*G;Dk}?v3lFk z9m6L*zX&`Lrx%kKF2?1{+Hd0WE+SMU_MR7Gjx0lNWvkSxqzpB!5I{$0&?W5;l+`&* zA&5a2=WcT)OoMkTc!W8Tc7k$h--H3PZRLmFq_|_rc>S`J4`uz*oDj7HH$#|zqJOF( zEGd?`b=-S{&5}{o*(Ak)ohQ=lW~=OM{&DW*a0#8+CvJ=S#vOGL%382JM-tflJ4%5x z-#^C{3PGBn3M`JYg*7njW;$C~qXvR7he)Fx z9LX{-#k{Pd6@T_Tu6mpD`vtXW{AlvF(+k)EiQ=DHubZ1YnB114(%AT`hFq*T8*z)7 z7Fq|#(?9FWowo1{3{e-+X*ekzyS6s9h|3QI5{XC|; zTUkeYT-esri3`k?h(tGL_+voeRsU1qwE_g*sWLgH9ryCa6%ThO`H=5BI1B3eFC_vfq81w{d3HdXPisNC1UF{*ke zZ)iA+e!X9O(#u}w7$u_3`OfEg%01U1u_OJM%3p5yq(=VJfr0Y5;cA4|V!8B(FExB^ zsvj~hT6p_&`=%*jj-llNPhI0^x}_Dq4r_N&eB{rh=)a8)*)F1PQ`em*Hon87ATvFM z@44|ZXf%O=+6qLV3;$)GpvEH#eB_UklBivJBThk*C4sNdlz$_Gzm2>VVuSly}22pO|)tM=eCxtvd4~>xr=b#?>k`&_M0@VMR=UN<|q9Z^psrP z>Nmus{pJtf;um;0A#T4%JDRI zdzU(XR|uI5!YF2WeAW`$1LF*oZ!eu|yYBPN+Zj0*=-woXn2_SNR93B9!6)n&r>3tS zTy9zjbdbc8l?_~>sK$XZUQEB-d$&eD{i%V)k)%>OsXD~OFzdm}WYLr$Bh7vsZxR<(Mi{2B+^p)g?iDY!~C zyEjpBB8fH33JoLHyW1y9YkV(zHavj27;xF9I^B4j0I0hh|5A6W1}x^PPxm`tN;MCE zvWxVZ@1~sZ$>id^g=`@^tmaxU(xPqew7#S)nm1OP^meCNC3?-YRjYF)ML#f^Cq3O$ z_aeRN_Z}+Brby+&QXtz-V2uCbV=1>%^_!kY`6I720Y1D}0$N+i@c}-E>nBmq_%ClIK!ddQIr=H_PDxargrs=*DYhj%N@6K$08+ zXuKuZJt1gXiNN1L>Wzp$oP#}S zO24S2l8qX9huFb|jM89pn~_QG80(^ox8Rmohn)OC7-fIo6L|rFgu<>UB=w+|8y9h1 z5>PY_?7mP*WOQR!%}YY-hG{hK0QL5sCq)~&o5Mw}NIaO1mUAW+ROB5M?Lz)_<8GYr zfn=kyqhY5W|AK~=*~4xt>m1t&ukL-%R=Kh|I0d+qn#tA6Ib|t$mRV&l=S_`7z1P7z z!JM3=lzZvhEe?Uwn_S0d4FOj4!3PnKCH$IE2|SAG4cbpG82Vli(jImw-QOJ23lXhZ zDEtrYb~6!$aM2o!!0zAc?u`$hU(S^nShhyVH35}Z*0IAVw};F7d=Zjo4B^zFm6I<} zQZd$D!B87uKJrRCdRe&uJ1ZrzLO;_HALa^vqk3Sh>n3n?#0KnKu9d+5j^tZym6X|y zoUs>df*+*5P4`;#$rF87k)`4)=fvKO6#iwc{7&D<pp;a2kZDw zZ{J|N<{=dvl-hsjsnWkx%weom#KfQw9#=LvrOgA1$g+_!G*LMoIr9+oc5OHiu=f4n z{E=wgf#W4zZk5IcqcHjE487^`L($sn$LSGowbddDJRD)Ma$1`i0THewrIk&yc8c>h?4t)BGIT?n^CqZ1Ri5O4dn$Bn>Zw`%*w=9M^Q)`gU5Z>qTa zj4D4lWqYYHYic||dPCutHlgDIA+clS`yPT94svl=*nUpa^XQjW*KEol`uh0^-7VWOkab-KjjRN z0v_ImI2azSARH2d_9M;Sqk6>pInuH-rBH! z34yYtRK72gTdBgX?oiST2IZhzsgZ(Ape()37imJaPdo|qVC&xKN~BG> zdOIay^pRtL=H1qLyJY|^)RJ$GZa(mnARKl$T4ZJsUHyT=tSsuPnlOL>83#hJFy#H zZiam+mGvg1MS{=-H?freudOrjN;+NRxXnzXWeuj5*EFr$Sngm+MJAM2D-AKxT*@q^ zbkIpMbh1!UCoq>}N>Qc|%?$P^giMN6{ZZC&G1x2d|p7!<&h3?Sz1tlppXo3~$7)wAr5=I=65w$p1+N7JQSo-}sa!o<)CRk~%&!jcrQ zKflM#todULQ!T%fk|Ama6%|DQW6n9SYx8NqB$JN{wnbuq2fedq1lgTV--G9+B6+H+!6NVaslvuvb|{$7 z;5i0mqj&a0*XWnKVdSX!ZgBiIx`OFW!4RI=r+o zy0=)4qx75bra1C^!M3hA2njqnKc;L`$}<^;Z-L`4G}hqHHj3{8PioBKl{$AXH|P(14iz=H6V}3ztH=IDPRjb;8y2a$UI==@l*! z?9Qb_o{V(%k#rks2KjN2Cago*$p%L2r+5+0x^1@^)7`Bt0glyITJU(XX}a#Qtral$ z?{0IxpGtG>p8HGHX!bF=IjLYz-5w$XnQ8GdXlv@j z>dF*P4&J=M>(0zkn#1$hX&D2o;;+(^VC^sT7ztOJN;dvlN$tO#bGm3@ClUjgXr-d> zS{l%=Wd#`d6mBU{2PFWlE$*rv1!XldkAQGxwkzr`#zo2iSL-hP+Gib?4pNHf-~07u zBW?hK+*a`ZwB}3<#BoDEUG4F3)f=R_ucEoA#sC^|*=IY$o-eY=Qjg+Aa+RZ=Xy0b8 zqKXM$(qhOI$rR4A7nIWJc9z!>ZaOaP1OCpa@n-axJ1{&gLQy>TuM9^IRG@cR(DLfl zgg(15ouKtaM&&EN}sx}-F6aq zKdg|OZ43^Y>6Nr}l1^;*`A0iY%noC^WmO<+EKk{bmJ}68bJ?yK2~`&*$=)}d5(T>P zVwA4lUjA6{fLnOD?>jg3JP(1U-eMef<-XQ7!}F!uqi)>Q4|%*c$7txIUG9)g`=3y- zL34j3x|n34B`Oixn7>{?9zwcRdR%F)4D_o-VTdI#CrncvH!=fY5)ADmtJ=t9r!7AA<)Oqe%_M2J_#X7 zM!;lju#7Dbk5NFM|LHxq4V!Fn-uMAKqv|5LeZ4BeF>Ucz5XW>Y#q0Ggtr%MZUnev=E5We- zp=kmR`?2Gc(Y4kili{Yn2O7Km2P~#u&H3{;@Qc>UBQ7xml_|xS;n8Chg_r_D%maL0 z_$)p{hY_(fU_dgG!7=_Fm|dRQHC2L2w~Ehs#t`y0-+;cVJSo$guGc1Chldzp|aO3>GfErNMSOkQz7dF zt(Gz5BYY|0TNWGfAD;0QQX=u$q`vHTVwpsdMwFz*ehxtpOBBa)L@dS1=v@jz9#$PP z-7OHdf