Quantcast
Channel: CSDN博客推荐文章
Viewing all 35570 articles
Browse latest View live

Mysql学习总结(50)——Oracle,mysql和SQL Server的区别

$
0
0
1,这三个数据库不是同一个公司的产品;
2、其所对应的使用对象也不一样,oracle是主流的大型数据库,大多数电信项目都是使用的oracle,而sqlserver与mysql主要是个人以及小型公司使用的的数据库,但是sqlserver需要收费,mysql不用;
3、如果按功能上来说,oracle最为强大,oracle支持递归查询,二后两者不支持;
4、三个数据库中,只有sqlserver有完整的图形化操作界面,而oracle与mysql都要借助于其他的第三方数据库图形操作界面,比如oracle用的大多都是plsql;
一、sqlserver
优点:
易用性、适合分布式组织的可伸缩性、用于决策支持的数据仓库功能、与许多其他服务器软件紧密关联的集成性、良好的性价比等;
为数据管理与分析带来了灵活性,允许单位在快速变化的环境中从容响应,从而获得竞争优势。从数据管理和分析角度看,将原始数据转化为商业智能和充分利用Web带来的机会非常重要。作为一个完备的数据库和数据分析包,SQLServer为快速开发新一代企业级商业应用程序、为企业赢得核心竞争优势打开了胜利之门。作为重要的基准测试可伸缩性和速度奖的记录保持者,SQLServer是一个具备完全Web支持的数据库产品,提供了对可扩展标记语言 (XML)的核心支持以及在Internet上和防火墙外进行查询的能力;
缺点:
开放性 :SQL Server 只能windows上运行没有丝毫开放性操作系统系统稳定对数据库十分重要Windows9X系列产品偏重于桌面应用NT server只适合小型企业而且windows平台靠性安全性和伸缩性非常有限象unix样久经考验尤其处理大数据库;
伸缩性并行性 :SQL server 并行实施和共存模型并成熟难处理日益增多用户数和数据卷伸缩性有限;
安全性:没有获得任何安全证书。
性能 :SQL Server 多用户时性能佳 ;
客户端支持及应用模式: 客户端支持及应用模式。只支持C/S模式,SQL Server C/S结构只支持windows客户用ADO、DAO、OLEDB、ODBC连接;
使用风险:SQL server 完全重写代码经历了长期测试断延迟许多功能需要时间来证明并十分兼容;
二、Oracle
优点:
开放性:Oracle 能所有主流平台上运行(包括 windows)完全支持所有工业标准采用完全开放策略使客户选择适合解决方案对开发商全力支持;
可伸缩性,并行性:Oracle 并行服务器通过使组结点共享同簇工作来扩展windownt能力提供高用性和高伸缩性簇解决方案windowsNT能满足需要用户把数据库移UNIXOracle并行服务器对各种UNIX平台集群机制都有着相当高集成度;
安全性:获得最高认证级别的ISO标准认证。
性能:Oracle 性能高 保持开放平台下TPC-D和TPC-C世界记录;
客户端支持及应用模式:Oracle 多层次网络计算支持多种工业标准用ODBC、JDBC、OCI等网络客户连接
使用风险:Oracle 长时间开发经验完全向下兼容得广泛应用地风险低
缺点:
对硬件的要求很高;
价格比较昂贵;
管理维护麻烦一些;
操作比较复杂,需要技术含量较高;
三、MySql
优点:
体积小、速度快、总体拥有成本低,开源;
支持多种操作系统;
是开源数据库,提供的接口支持多种语言连接操作
MySql的核心程序采用完全的多线程编程。线程是轻量级的进程,它可以灵活地为用户提供服务,而不过多的系统资源。用多线程和C语言实现的MySql能很容易充分利用CPU;
MySql有一个非常灵活而且安全的权限和口令系统。当客户与MySql服务器连接时,他们之间所有的口令传送被加密,而且MySql支持主机认证;
支持ODBC for Windows, 支持所有的ODBC 2.5函数和其他许多函数, 可以用Access连接MySql服务器, 使得应用被扩展;
支持大型的数据库, 可以方便地支持上千万条记录的数据库。作为一个开放源代码的数据库,可以针对不同的应用进行相应的修改。
拥有一个非常快速而且稳定的基于线程的内存分配系统,可以持续使用面不必担心其稳定性;
MySQL同时提供高度多样性,能够提供很多不同的使用者介面,包括命令行客户端操作,网页浏览器,以及各式各样的程序语言介面,例如C+,Perl,Java,PHP,以及Python。你可以使用事先包装好的客户端,或者干脆自己写一个合适的应用程序。MySQL可用于Unix,Windows,以及OS/2等平台,因此它可以用在个人电脑或者是服务器上;
缺点:
不支持热备份;
MySQL最大的缺点是其安全系统,主要是复杂而非标准,另外只有到调用mysqladmin来重读用户权限时才发生改变;
没有一种存储过程(Stored Procedure)语言,这是对习惯于企业级数据库的程序员的最大限制;
MySQL的价格随平台和安装方式变化。Linux的MySQL如果由用户自己或系统管理员而不是第三方安装则是免费的,第三方案则必须付许可费。Unix或Linux 自行安装 免费 、Unix或Linux 第三方安装 收费;
作者:u012562943 发表于2017/11/26 11:55:19 原文链接
阅读:55 评论:0 查看评论

python设计模式之观察者模式

$
0
0


一、行为型模式简介

           1. 创建型模式的工作原理是基于对象的创建机制的。由于这些模式隔离了对象的创建细节,所以使得代码能够与要创建的对象的类型相互独立。

           2. 结构型模式用于设计对象和类的结构,从而使他们可以相互协作以获得更大的结构。重点在于简化结构以及识别类和对象之间的关系。

           3. 行为型模式重点关注的是对象的责任。他们用来处理对象之间的交互,以实现更大的功能。行为型模式:对象之间应该能够彼此交互,同时还应该是松散耦合的。


二、理解观察者设计模式

       目标:

           1. 它定义了对象之间的一对多的依赖关系,从而使得一个对象中的任何更改都将自动通知其他依赖对象。

           2. 它封装了主题的核心组件。

       使用场景:

           1. 在分布式系统中实现事件服务。

           2. 用作新闻机构的框架。

           3. 股票市场。 

       UML图:


          1. 主题(Subject):类Subject需要了解Observer。Subject类具有许多方法,诸如register()和deregister()等,Observer可以通过这些方法注册到Subject类中。因此,一个Subject可以处理多个Observer。

          2. 观察者(Observer):它为关注主题的对象定义了一个接口。它定义了Observer需要实现的各个方法,以便在主题发生变化时能够获得相应的通知。

          3. 具体观察者(ConcreteObserver):它用来保存应该与Subject的状态保持一致。它实现了Observer接口以保持其状态与主题中的变化相一致。


三、现实世界中的观察者模式

        新闻机构示例代码:

# -*- coding: UTF-8 -*-
from abc import ABCMeta, abstractmethod


# 订新闻的接口(主题)
class NewsPublisher:
    def __init__(self):
        self.__subscribers = []
        self.__latestNews = None

    # 提供注册
    def attch(self,subscriber):
        self.__subscribers.append(subscriber)

    # 提供注销
    def detach(self):
        return self.__subscribers.pop()

    # 返回已经订户列表
    def subscribers(self):
        return [type(x).__name__ for x in self.__subscribers]

    # 返回注册的所有用户
    def notifySubscribers(self):
        for sub in self.__subscribers:
            sub.update()

    # 创建新消息
    def addNews(self, news):
        self.__latestNews = news

    # 返回最新消息
    def getNews(self):
        return "Got News:",self.__latestNews


# 用户(观察者)
class Subscriber(metaclass=ABCMeta):
    @abstractmethod
    def update(self):
        pass


#  SMS用户(实际观察者)
class SMSSubscriber:
    def __init__(self,publisher):
        self.publisher = publisher
        self.publisher.attch(self)

    def update(self):
        print(type(self).__name__, self.publisher.getNews())


# 邮件用户(实际观察者)
class EmailSubscriber:
    def __init__(self,publisher):
        self.publisher = publisher
        self.publisher.attch(self)

    def update(self):
        print(type(self).__name__, self.publisher.getNews())

# 其他用户(实际观察者)
class AnyOtherSubscriber:
    def __init__(self,publisher):
        self.publisher = publisher
        self.publisher.attch(self)

    def update(self):
        print(type(self).__name__, self.publisher.getNews())


if __name__ == "__main__":
    news_publisher = NewsPublisher()
    for Subscribers in [SMSSubscriber,EmailSubscriber,AnyOtherSubscriber]:
        Subscribers(news_publisher)     # 观察者,向主题订阅
    print("\nSubscribers:",news_publisher.subscribers())
    news_publisher.addNews("Hello World!") # 增加消息
    news_publisher.notifySubscribers() # 发布消息
    print("\nDetached:",type(news_publisher.detach()).__name__) # 删除订阅者
    print("\nSubscribers:",news_publisher.subscribers()) # 查看订阅列表
    news_publisher.addNews("My second news") # 增加消息
    news_publisher.notifySubscribers() # 发布消息


四、观察者通知方式

     1.  拉模型

               1.1 每当发生变化时,主题都会向所有已注册的观察者进行广播。

               1.2 出现变化时,观察者负责获取相应变化情况,或者从订户那里拉去数据。

               1.3 拉模型效率较低,因为它涉及两个步骤。第一步,主题通知观察者,第二部,观察者从主题那里提取所需的数据。

       2. 推模型

               2.1 变化由主题推送到观察者。

               2.2 在拉模型中,主题可以向观察者发送详细的信息。当主题发送大量观察者永不到的数据时,会使相应时间过长。

               2.3 由于只从主题发送所需的数据,所以能够提高性能。


五、松耦合与观察者模式

        1.松耦合架构特性:

              1.1 降低一个元素内发生的更改可能对其他元素产生意外影响的风险。

              1.2 它使得测试、维护和故障排除工作更加简单。

              1.3 系统可以轻松地分解为可定义的元素。      

        2.观察者模式:

              2.1 主题对观察者唯一了解的就是实现一个特定的接口。同时不需要了解具体的观察者类。

              2.2 可以随时添加任意的新观察者。

              2.3 添加新观察者,根本不需要修改主题。

              2.4 观察者和主题没有绑定在一起,可以彼此独立使用。如果有需要,观察者可以在任何地方重用。

              2.5 观察者中的变化不会互相影响。


六、观察者模式:优点和缺点

        1. 优点:

              1.1 它使得彼此交互的对象之间保持松耦合。

              1.2 它使得我们可以在无需对主题或观察者进行任何修改的情况下,高效地发送数据到其他对象。

              1.3 可以随时添加/删除观察者。

        2. 缺点:

              2.1 观察者接口必须由具体观察者实现,而这涉及继承。无法进行组合,因为观察者接口可以实例化。

              2.2 如何实现不当的华,观察者可能会增加复杂性,并且导致性能降低。

              2.3 通知可能不可靠,并且导致竞争条件或不一致。


七、常见问答

        1. 可能存在多个主题和观察者吗?

               可能。这种情况,若要正常工作:需要通知观察者哪些主题发生了变化以及各个主题中发生了哪些变化。

         2. 谁负责触发更新?

               观察者模式可以在推模型和拉模型中工作。通常发生更新时,主题会触发更新方法,但有时可以根据应用程序的需要,观察者也是可以触发通知的。然而,需要注意的是频率不应该太高,否则则可能导致性能下降,特别是当主题的更新不太频繁时。

         3. 主题或观察者可以在任何其他用例中访问吗?

               都可以独立使用


作者:u013584315 发表于2017/11/26 12:17:06 原文链接
阅读:57 评论:0 查看评论

leetcode-100. Same Tree

$
0
0

100. Same Tree

Given two binary trees, write a function to check if they are the same or not.

Two binary trees are considered the same if they are structurally identical and the nodes have the same value.


Example 1:

Input:     1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

Output: true

Example 2:

Input:     1         1
          /           \
         2             2

        [1,2],     [1,null,2]

Output: false

Example 3:

Input:     1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

Output: false


题意:给定两个二叉树,判断这两个二叉树是否完全一致

思路:肯定想到遍历判断,并不难,主要是看看能不能优化

一开始自己写了个方法,4ms,beats 33%

然后看了排名靠前的代码, 提交了一下居然用了5ms,beats 8%,,再提交,4ms,,,

又找了个宣称1ms过的非递归解法,提交了两次,5ms,,beats 8%,,,,

这判题的方法真是迷。。。。。。


速度都差不多,就只列出了方法不同的解法:

递归:

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p==null&&q==null) return true;
        if(p==null||q==null) return false;
        if(p.val == q.val){
            return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
        }
        else return false;
    }
}


非递归:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q){

			if (p == null && q == null){
				return true;
			}else if (p == null || q == null){
				return false;
			}

			Stack<TreeNode> pStack = new Stack<>();
			Stack<TreeNode> qStack = new Stack<>();

			pStack.push(p);
			qStack.push(q);

			while (!(pStack.isEmpty() && qStack.isEmpty())) {
				TreeNode nq = qStack.pop();
				TreeNode np = pStack.pop();

				if (nq.val != np.val) {
					return false;
				}
				if (nq.left != null) {
					qStack.push(nq.left);
				}
				if (np.left != null) {
					pStack.push(np.left);
				}

				if (qStack.size() != pStack.size()) {
					return false;
				}

				if (nq.right != null) {
					qStack.push(nq.right);
				}
				if (np.right != null) {
					pStack.push(np.right);
				}
				if (pStack.size() != qStack.size()) {
					return false;
				}

			}

			return pStack.size() == qStack.size();
		}
}


作者:qq_32832023 发表于2017/11/26 12:56:52 原文链接
阅读:32 评论:0 查看评论

Java基础学习总结(120)——JVM 参数使用详细说明

$
0
0
一、什么是JVM?
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。
JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境.
1.创建JVM装载环境和配置
2.装载JVM.dll
3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装载并处理class类。
示例为默认值的不需要配置,使用默认设置
二、JVM参数说明
参数名称
含义
默认值
示例
说明
-Xms
初始堆大小
物理内存的1/64(<1GB) ,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM可以保留默认值
-Xms1000M
默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.
-Xmx
最大堆大小
物理内存的1/4(<1GB),最佳设值应该视物理内存大小及计算机内其他内存开销而定
-Xms1000M
默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制
-Xmn
年轻代大小(1.4or lator)
不熟悉最好保留默认值
默认值
注意:此处的大小是(eden+ 2 survivor space)。与jmap -heap中显示的New gen是不同的。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
-XX:NewSize
设置年轻代大小(for 1.3/1.4)
不需要设置
-XX:MaxNewSize
年轻代最大值(for 1.3/1.4)
不需要设置
-XX:PermSize
设置持久代(perm gen)初始值
物理内存的1/64,不熟悉保留默认值
默认值
-XX:MaxPermSize
设置持久代最大值
物理内存的1/4,不熟悉保留默认值
默认值
-Xss
每个线程的堆栈大小
JDK5.0 以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.
默认值
根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右,一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。(校长)和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"”-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了。
-XX:ThreadStackSize
Thread Stack Size
上面的-Xss不需要设置,如果要设置直接设置这个参数就可以
默认值
(0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.]
-XX:NewRatio
年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)
Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。
默认值
-XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。
-XX:SurvivorRatio
Eden区与Survivor区的大小比值
 
默认值
设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10
-XX:LargePageSizeInBytes
内存页的大小
=128m,不可设置过大, 会影响Perm的大小
默认值
128m
-XX:+UseFastAccessorMethods
原始类型的快速优化(jdk 1.6 or later)
-
默认值
-XX:+DisableExplicitGC
关闭System.gc()
-
默认值
这个参数需要严格的测试
-XX:MaxTenuringThreshold
垃圾最大年龄,表示对象被移到老年代的年龄阈值的最大值
15
默认值
控制对象能经过几次GC才被转移到老年代。回收如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概率。该参数只有在串行GC时才有效。
-XX:+AggressiveOpts
加快编译
-
默认值
启用该选项之后,需要考虑到性能的提升,同样也需要考虑到性能提升所带来的不稳定风险。
-XX:+UseBiasedLocking
锁机制的性能改善 (Java 5 update 6 or later)
+
默认值
Java 5 HotSpot JDK需要明确的命令来启用这个特性,在使用-XX:+AggressiveOpts选项,有偏见的锁会Java 5中会被自动启用。在Java 6中是默认启用的。
-XX:TLABWasteTargetPercent
TLAB占eden区的百分比
1%
默认值
-XX:+CollectGen0First
FullGC时是否先YGC
false
默认值
三、收集器相关参数
参数名称
含义
默认值
示例
说明
-XX:+UseParNewGC
设置年轻代为并行收集
-
+
可与CMS收集同时使用,JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值
-XX:ParallelGCThreads
并行收集器的线程数
默认为CPU核心数
默认值
此值最好配置与处理器数目相等 同样适用于CMS
-XX:+UseConcMarkSweepGC
使用CMS内存收集
-
+
注意最新的JVM版本,当开启此选项时,-XX:UseParNewGC会自动开启。因此,如果年轻代的并行GC不想开启,可以通过设置-XX:-UseParNewGC来关掉。
-XX:ParallelCMSThreads
CMS并发收集线程数
默认为CPU核心数
默认值
如果还标志未设置,JVM会根据并行收集器中的-XX:ParallelGCThreads参数的值来计算出默认的并行CMS线程数。该公式是ConcGCThreads = (ParallelGCThreads + 3)/4。因此,对于CMS收集器, -XX:ParallelGCThreads标志不仅影响“stop-the-world”垃圾收集阶段,还影响并发阶段。总之,有不少方法可以配置CMS收集器的多线程执行。正是由于这个原因,建议第一次运行CMS收集器时使用其默认设置, 然后如果需要调优再进行测试
-XX:+UseCMSCompactAtFullCollection
在FULL GC的时候, 对年老代的压缩
-
+
CMS是不会移动内存的, 因此, 这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 增加这个参数是个好习惯。可能会影响性能,但是可以消除碎片
-XX:CMSFullGCsBeforeCompaction
full gc多少次后进行内存压缩
默认为0
默认值
由于并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次GC以后对内存空间进行压缩,整理.
-XX:CMSInitiatingOccupancyFraction
老年代使用70%后开始CMS收集
=92
=75
为了保证不出现promotion failed(见下面介绍)错误,该值的设置需要满足以下公式
-XX:+CMSClassUnloadingEnabled
持久代使用CMS并发收集
jdk1.7默认关闭,1.8默认打开
-
它会增加CMS remark的暂停时间,如果没有程序产生大量的临时类,新类加载并不频繁,这个参数还是不开的好
-XX:CMSInitiatingPermOccupancyFraction
设置Perm Gen使用到达多少比率时触发
=92
默认值
四、日志相关参数
参数名称
含义
默认值
示例
说明
-Xloggc
记录日志文件位置
/data/log/jetty/gc.log
-XX:+PrintGCDateStamps
打印可读的日期而不是时间戳
-
+
-XX:+PrintGCDetails
打印日志详情
-
+
输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs][GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]
-XX:+PrintGCApplicationStoppedTime
打印GC停顿时间
-
+
它除了打印清晰的GC停顿时间外,还可以打印其他的停顿时间,比如取消偏向锁,class 被agent redefine,code deoptimization等等,有助于发现一些原来没想到的问题,建议也加上。输出形式:Total time for which application threads were stopped: 0.0468229 seconds
-XX:+PrintCommandLineFlags
打印已配置的XX类参数
-
+
打印出命令行里设置了的参数以及因为这些参数隐式影响的参数,比如开了CMS后,-XX:+UseParNewGC也被自动打开
-XX:+HeapDumpOnOutOfMemoryError
输出Heap Dump到指定文件
-
+
在Out Of Memory,JVM快死快死掉的时候,输出Heap Dump到指定文件。不然开发很多时候还真不知道怎么重现错误。路径只指向目录,JVM会保持文件名的唯一性,叫java_pid${pid}.hprof。如果指向文件,而文件已存在,反而不能写入。
-XX:HeapDumpPath
设置Heap Dump输出路径
=${LOGDIR}/
五、JAVA文件相关配置
-Dcom.meizu.properties.key=x1YfmdjyFdu68KJ
-Dcom.meizu.properties.encrypt=true
-Djava.io.tmpdir=/dev/shm
-Dfile.encoding=UTF-8
-Dsun.jnu.encoding=UTF-8
-Dsun.net.http.allowRestrictedHeaders=true

作者:u012562943 发表于2017/11/26 13:09:33 原文链接
阅读:15 评论:0 查看评论

Maven学习总结(42)——Maven多模块构建中常用的参数

$
0
0
一、多模块项目中需要使用不同的参数实现不同的构建目的,常用参数:
-am --also-make:同时构建所列模块的依赖模块;
-amd -also-make-dependents:同时构建依赖于所列模块的模块;
-pl --projects <arg>:构建制定的模块,模块间用逗号分隔;
-rf -resume-from <arg>:从指定的模块恢复反应堆。
假设有聚合模块:jborg,包含如下几个子模块:jborg-core、jborg-bash,jborg-auth、jborg-web、jborg-sys-web。两个web模块依赖于jborg-core
jborg
|--jborg-core
|--jborg-web
|--jborg-sys-web
|--pom.xml
二、-pl 构建制定模块
mvn clean install -pl jborg-web 只构建web模块,这里一次可以指定多个模块用逗号分隔
三、-am 选项可以同时构建所列模块的依赖模块。
mvn clean install -pl jborg-web -am 构建jborg-web的同时会构建它依赖的jborg-core
四、-amd 选项可以同时构建依赖于所列模块的模块,与am相反。
mvn clean install -pl jborg-core -amd
会构建core和两个web模块
五、-rf 选项可以在完整的反应堆构建顺序基础上,指定从哪个模块开始构建。
mvn clean install -rf account-web ,由于web位于第二,它之后有account-sys-web,因此会构建两个web模块
作者:u012562943 发表于2017/11/26 13:24:14 原文链接
阅读:26 评论:0 查看评论

Spring学习总结(24)——Spring配置文件加载路径总结

$
0
0
1. Spring使用ClassPathXmlApplicationContext 从classpath读取
ClassPathXmlApplicationContext 默认会去 classPath 路径下找。classPath 路径指的就是编译后的 classes 目录。
1.1 如果配置文件在classpath目录下:
ClassPathXmlApplicationContext tx = new ClassPathXmlApplicationContext("appContext2.xml");
1.2 如果一个包专门用来存配置文件
ClassPathXmlApplicationContext tx = new ClassPathXmlApplicationContext("//my/config/appContext2.xml");
或者
ClassPathXmlApplicationContext tx = new ClassPathXmlApplicationContext("my/config/appContext2.xml");
其实这两种都是相对于classpath路径的路径
1.3 也可以绝对路径获取,但是路径前要加“file”
BeanFactory beanFactory = new ClassPathXmlApplicationContext("file:E:projectsrcmainesourcesapplicationContext.xml");
2. Spring使用FileSystemXmlApplicationContext加载
FileSystemXmlApplicationContext 默认是去项目的路径下加载,可以是相对路径,也可以是绝对路径,若是绝对路径,“file:” 前缀可以缺省。
2.1 使用FileSystemXmlApplicationContext也可以从classpath加载,要在路径前添加classpath前缀
FileSystemXmlApplicationContext tx = new FileSystemXmlApplicationContext("classpath:my/config/appContext2.xml");
2.2 以绝对路径形式加载
FileSystemXmlApplicationContext tx = new FileSystemXmlApplicationContext("d:/my/config/appContext2.xml");
当然 这里比较好的做法是程序运行期间动态的算出绝对路径,避免直接在代码里写死一个绝对路径。
3. SpringMvc使用WebApplicationContext
在Web项目中,可以使用ContextLoaderListener 自动装配ApplicationContext的信息。
在web.xml文件中创建监听器:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
配置配置文件路径
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/appContext.xml</param-value>
</context-param>
ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
如果在web.xml中不写任何参数配置信息,默认的路径是"/WEB-INF/applicationContext.xml, 在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml。
如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数: 在<param-value> </param-value>里指定相应的xml文件名,如果有多个xml文件,可以写在一起并以“,”号分隔。
也可以这样applicationContext-*.xml采用通配符,比如这那个目录下有applicationContext-ibatis-base.xml,
applicationContext-action.xml,applicationContext-ibatis-dao.xml等文件,都会一同被载入。
4. Java中的路径读取
封装一个方法获取classpath绝对路径:
public static String getRealPath(String file) {
String path = PathUtils.class.getClassLoader().getResource(file).getPath();
return path;
}
class.getResource("")要想获得文件的路径,得从最终生成的.class文件为着手点,再结合相对路径的概念,就可以准确地定位资源文件了。不同的IDEbuild出来是不同的位置下的,不过都是以顶层package作为根目录,比如在Web应用中,有一个WEB-INF的目录,WEB-INF目录里面除了web.xml文件外,还有一个classes目录,它就是这个WEB应用的package的顶层目录,也是所有.class的根目录“/”,假如clasaes目录下面有一个mynewfile.txt文件,它的相对路径就是"/mynewfile.txt",如果相对路径不是以"/"开头,那么它就是相对于.class的路径。
class.getClassLoader().getResource 如果是getClassLoader().getResource,路径前加不加"/"都是可以的,比如Home.class.getClassLoader().getResource("my/config/file1.html")和Home.class.getClassLoader().getResource("/my/config/file1.html")都是可以的。
还有一个getResourceAsStream()方法,参数是与getResouce()方法是一样的,它相当于你用getResource()取得File文件后,再new InputStream(file)一样的结果
作者:u012562943 发表于2017/11/26 13:32:16 原文链接
阅读:24 评论:0 查看评论

VS Code 折腾记 - (10) 你想发布自己捣鼓的snippets到VSCode插件市场!

$
0
0

前言

趁着周六日的空闲时间,了解了下vscode插件或者代码片段的发布套路.

本来找下GG有啥文章前人走过的文章,最后似乎木有,那就只能自己摸索了.

从官方文档入手!!实践出真理….

em..自认为英文不错和自学能力的大佬灰常灰常好的,到这里可以停止阅读了,省的浪费时间!

学会这个,你能收获什么?见仁见智…

但是起码你知道怎么发布了,且对 npmpackage.json会有更深一层的理解.


发布的大体流程

  1. 有个微软的账号
  2. 登录市场,创造一个团队
  3. 创建一个 Personal Access token
  4. 全局安装vsce模块
  5. github 新建一个对应的仓库
    • 核心要点,package.json的书写
    • snippets的 json 文件
    • 对应的静态文件等(image)
  6. 最后一步就是发布,看我们自己的发布的成果了

1.微软帐号

em……自己创建,之后访问vscode maketplace

传送门: VSCode marketplace => sign in(登录)

右上角还有官方的两篇文档:


2.登录市场,创建一个团队

你刚登录帐号,看到的页面是这个.

这里写图片描述

是不是一脸懵逼!!!我刚登录也是一脸懵逼…

那个Upload new extension是什么鬼!

其实这里是你有插件发布之后,一个汇总平台!!(记住是插件拓展!)

可以简化更新流程,直接上传封装好的插件..

这里写图片描述

如图所示,微软的插件商店是涵盖三个平台的..我们点进去Visual Studio Code瞅瞅!

这里写图片描述

拖拉上传VSIX格式?其实这个就是 VSCode 插件的主体文件…你发布过插件的话,直接拖拉新的可以直接更新版本(发布)

说了这么多,只是科普而已…我们现在可木有发布过,说说我们要关注的..

点击你登录的用户名

进来是纯英文的,没错…想改中文,头像?so easy !

这里写图片描述

个人信息编辑这块不说,说说创建团队服务的的.因为没有团队..你拿不到Personal Access Token

这里写图片描述

到下一步还有一些选择,直接选择亚太就行了…我操作的时候是英文操作的,然后去找了下是否有中文显示的…

3.创建一个 Personal Access Token

其实这货就跟 Github 的Access Token差不多的一个玩意,用来允许访问凭证(可控!因为可以部分功能开放)

点进去团队之后,右上角,如图所示

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

如上所示的,红圈那一串就是发布用到的 token 了!!!
自己保留!,不会永久显示的!!重新登录帐号这些就再也看不到了

4.安装 VSCE

依赖于node: npm install -g vsce ; 说下命令行的参数…

  # vsce --help

  Usage: vsce [options] [command]


  Options:

    -V, --version  output the version number
    -h, --help     output usage information

 Commands:

    ls [options]                         列出实际会发布的文件列表
    package [options]                    打包成一个插件
    publish [options] [<version>]        发布插件
    unpublish [options] [<extensionid>]  插件下架
    list <publisher>                     列出某个发布者下所有发布的,需要配置好token 额,不然会提示输入
    ls-publishers                        列出所有已知的发布者
    create-publisher <publisher>         创建一个新的发布者
    delete-publisher <publisher>         删除一个发布者
    login <publisher>                    登录一个发布者到发布者列表中
    logout <publisher>                   反之,退出发布者

注意注意: token 要保留, 若是退出后登录还是第一次登录都是需要这个的,发布也是!!!
登录后不退出,凭证默认是保留在本地的….不过还是要保留吧!!!也许哪天还要用到!!

5.软件仓库!

  • 新建仓库,关联仓库这些跳过!,跳过
  • snippet 的书写姿势!!跳过,自行去了解,挺多可配置的…
  • package.json — 这个就是我要说的…摸索了挺久..

先看看目录结构


├── LICENSE  // 仓库使用的协议
├── README.md  // 基础描述
├── gif  // 文件夹,存放动态图的
├── icon  //插件图片存放的地方,要求128X128
│   └── icon.png
├── package.json  // 发布的条条框框限制和配置
├── .gitignore // git 忽略文件
├── .vscodeignore  // vscode 提交专有的忽略文件
├── snippets  // 代码片段存放地方
│   ├── vue-typescript.json
│   └── vue.json
└── vscode-vue-ts-snippet-0.0.1.vsix // 打包的插件,snippets没卵用的,一般用于插件!
//snippet 打包成插件并不能执行,打包命令 vsce package 

package.json

package.json看我的注释吧,实际文件不能注释的.
不然会报 JSON 错误或者无效


{
  "name": "vscode-vue-ts-snippet", // 包名
  "version": "0.0.1", // 版本h号
  "description": "Vue with Typescript snippets", // 包的描述
  "icon": "icon/icon.png", // 显示插件的图标
  "publisher": "crperlin", // vscode 插件自有的属性,发布人
  "repository": { // 包的存放仓库
    "type": "git", // 类型 git
    "url":"https://github.com/crper/vscode-vs-ts-snippets.git" // 访问链接
  },
  "galleryBanner": { // 横幅描述
    "color": "#0273D4",
    "theme": "dark"
  },
  "scripts": { // 这里没用到,一般用来写拓展才用到,跑测试什么的
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": ["vue","typescript-vue","typescript","vue-snippets","vue-ts-snippets","vue-typescript-snippets","vue2+"],  // 关键字,就是可一个人去搜索的
  "engines": { // 限制 vscode 的版本
    "vscode": "^1.18.0"
  },
  "author":{ // 不言而喻,发布人的一些基础信息
    "name": "crper(QunHe Lin)",
    "email": "crper@outlook.com",
    "url": "https://github.com/crper"
  },
  "categories": [ // 插件的归类
    "Snippets",
    "Other"
  ],
  "contributes":{ // 这里就是索引 snippet 的,如何让插件知道你共享的东西
    "snippets": [
      {
        "language": "vue", // 针对.vue 格式的 snippets
        "path":"./snippets/vue.json"
      },
      {
        "language": "typescript", // 针对.typescript 的 snippets
        "path":"./snippets/vue-typescript.json"
      },
      {
        "language": "javascript", // 针对.js 的 snippets
        "path":"./snippets/vue-typescript.json"
      }
    ]
  },
  "bugs": {  // 一般就是反馈 bug,issue 的路径
    "url": "https://github.com/crper/vscode-vs-ts-snippets/issues"
  },
  "homepage": "https://github.com/crper/vscode-vs-ts-snippets/readme", // 包的主页,就是放在哪里
  "license": "SEE LICENSE IN LICENSE" // 包使用的协议!
}

更多的package.json字段及作用请看这里: npm package.json help

6. 发布,查看成果

这里写图片描述

我的测试 snippet, 传送门: vue-ts-snippet ;

不推荐安装哈!!!只是测试用..当然,各位大佬愿意帮我维护的话,画上一段时间到时候可以变成一个有用的 snippets


总结

至此,你想要自己写一个代码片段的库发布到商店造福他人,
应该是没什么难度了…

下一篇文章,我再给大伙分享一波实用的插件!!!!敬请期待!!!

这里写图片描述

em….依旧来一波问题的提问姿势

这里写图片描述

作者:bomess 发表于2017/11/26 14:00:42 原文链接
阅读:0 评论:0 查看评论

[bzoj1832][lca]聚会

$
0
0

Description

Y岛风景美丽宜人,气候温和,物产丰富。Y岛上有N个城市,有N-1条城市间的道路连接着它们。每一条道路都连接某两个城市。幸运的是,小可可通过这些道路可以走遍Y岛的所有城市。神奇的是,乘车经过每条道路所需要的费用都是一样的。小可可,小卡卡和小YY经常想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小。
由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成。他们会提供给你地图以及若干次聚会前他们所处的位置,希望你为他们的每一次聚会选择一个合适的地点。

Input

第一行两个正整数,N和M。分别表示城市个数和聚会次数。后面有N-1行,每行用两个正整数A和B表示编号为A和编号为B的城市之间有一条路。城市的编号是从1到N的。再后面有M行,每行用三个正整数表示一次聚会的情况:小可可所在的城市编号,小卡卡所在的城市编号以及小YY所在的城市编号。

Output

一共有M行,每行两个数Pos和Cost,用一个空格隔开。表示第i次聚会的地点选择在编号为Pos的城市,总共的费用是经过Cost条道路所花费的费用。

Sample Input

6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6

Sample Output

5 2
2 5
4 1
6 0

HINT

数据范围:
100%的数据中,N<=500000,M<=500000。
40%的数据中N<=2000,M<=2000。

题解

哇塞一道水题,bzoj居然会有这样的好东西嘿嘿嘿
这个。。很明显可以看出,答案一定在这三个数的lca之一嘛。口胡一下,如果聚会点不在lca上,譬如在lca的父亲节点。那么深度较深的两个节点走到这里的花费就要多2,而较浅的节点走到这里的花费只少了1。暴力三个lca然后算出余下的一个节点到这个lca的权,记录答案即可
因为这题所有边权相同哈哈哈哈哈就可以lca水过了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
    int x,y,next;
}a[1110000];int len,last[510000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int bin[22],n,m;
int fa[510000][22],dep[510000];
void pre_tree_node(int x)
{
    for(int i=1;i<=20 && bin[i]<=dep[x];i++)fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(y!=fa[x][0])
        {
            fa[y][0]=x;
            dep[y]=dep[x]+1;
            pre_tree_node(y);
        }
    }
}
int lca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    for(int i=20;i>=0;i--)
        if(dep[x]-dep[y]>=bin[i])x=fa[x][i];
    if(x==y)return x;
    for(int i=20;i>=0;i--)if(dep[x]>=bin[i] && fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
int u[4];
bool cmp(int n1,int n2){return dep[n1]<dep[n2];}
int main()
{
    scanf("%d%d",&n,&m);
    bin[0]=1;
    for(int i=1;i<=20;i++)bin[i]=bin[i-1]*2;
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ins(x,y);ins(y,x);
    }
    dep[1]=1;fa[1][0]=0;pre_tree_node(1);
    while(m--)
    {
        int ans=999999999;
        scanf("%d%d%d",&u[1],&u[2],&u[3]);
        sort(u+1,u+1+3,cmp);
        int num,cnt,tmp,ret;
        cnt=0;;
        num=lca(u[1],u[2]);
        cnt+=dep[u[1]]+dep[u[2]]-dep[num]*2;
        tmp=lca(num,u[3]);
        cnt+=dep[u[3]]+dep[num]-dep[tmp]*2;
        if(ans>cnt)ans=cnt,ret=num;

        cnt=0;
        num=lca(u[1],u[3]);
        cnt+=dep[u[1]]+dep[u[3]]-dep[num]*2;
        tmp=lca(num,u[2]);
        cnt+=dep[u[2]]+dep[num]-dep[tmp]*2;
        if(ans>cnt)ans=cnt,ret=num;

        cnt=0;
        num=lca(u[2],u[3]);
        cnt+=dep[u[2]]+dep[u[3]]-dep[num]*2;
        tmp=lca(num,u[1]);
        cnt+=dep[u[1]]+dep[num]-dep[tmp]*2;
        if(ans>cnt)ans=cnt,ret=num;
        printf("%d %d\n",ret,ans);
    }
    return 0;
}
作者:Rose_max 发表于2017/11/26 14:41:26 原文链接
阅读:42 评论:0 查看评论

线程条件队列ConditionObject源码解读

$
0
0

小记
好久没更博,窗外光芒万丈,冬日的晚晨,多么美好,就不浪费了,循着键盘上的点点星辰,开工!

啥子是条件队列?

我们都知道,在万类之祖Object里面定义了几个监视器方法:wait(),notify
(),notifyAll(),配合synchronized语义来控制线程的一些状态,在JDK1.5之后,由Lock替代了synchronized,而这几个监视器由条件队列Condition来实现,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”),以原子的方式释放锁,并挂起当前线程,所以,也可以叫它为线程的条件队列(自创的)。

来看一个应用示例

在以前刚学习Java的时候写过一个题,题干大概是这样的:开启三个线程依次轮流打印出75个数,且次序不能乱。下面是代码:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CountTo_75 {

    public static void main(String[] args) {
        final Box box = new Box();

        new Thread(new Runnable() { // 线程1
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    box.main_1();
                }
            }
        },"Thread-1").start();
        new Thread(new Runnable() { // 线程2
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    box.main_2();
                }
            }
        },"Thread-2").start();
        new Thread(new Runnable() { // 线程3
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    box.main_3();
                }
            }
        },"Thread-3").start();
    }

    static class Box {
        Lock lock = new ReentrantLock();
        Condition condition_1 = lock.newCondition();
        Condition condition_2 = lock.newCondition();
        Condition condition_3 = lock.newCondition();
        private volatile int flag = 1;
        public static int count = 0;   //用于计数的变量

        public void main_1() {
            lock.lock();
            try {
                while(flag != 1){
                    try {
                        condition_1.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int j = 0; j < 5; j++) {
                    count++;
                    System.out.println(Thread.currentThread().getName() +" "+ count);
                }
                flag = 2;
                condition_2.signal();
            } finally {
                lock.unlock();
            }
        }

        public void main_2() {
            lock.lock();
            try {
                while(flag != 2){
                    try {
                        condition_2.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int j = 0; j < 5; j++) {
                    count++;
                    System.out.println(Thread.currentThread().getName() +" " + count);
                }
                flag = 3;
                condition_3.signal();
            } finally {
                lock.unlock();
            }
        }

        public void main_3() {
            lock.lock();
            try {
                while(flag != 3){
                    try {
                        condition_3.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int j = 0; j < 5; j++) {
                    count++;
                    System.out.println(Thread.currentThread().getName() + " " + count);
                }
                flag = 1;
                condition_1.signal();
            } finally {
                lock.unlock();
            }
        }
    }
}

抛开当时混乱的逻辑和性能考虑不足不谈,这段丑陋的代码,终归是实现了功能,而且是运用了Lock和Condition来实现的,用在这里来说明Condition的语义再好不过了。代码中初始化了3个条件队列,分别来控制3个线程的挂起状态,flag变量则控制它们之间的关系。

与Lock之间的实现关系

Condition是一个接口,其实现类只有两个:AQS和AQLS,都以内部类的形式存在,内部类叫做ConditionObject,这里有点纳闷,既然这个类是为Lock专属定制的,为什么不在ReentrantLock里面来实现呢?放在AQS不会太臃肿吗?不知道Doug Lea上神当时是怎么考虑的。
由于在AQS中已经实现,因此在ReentrantLock里面对其操作也是很简单的,创建一个条件队列:

    public Condition newCondition() {
        return sync.newCondition();
    }

sync中的实现:

    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;
        final ConditionObject newCondition() {
            return new ConditionObject();
        }
    }

很简单吧?呵呵,下面来看ConditionObject

ConditionObject实现

首先定义了两个核心成员变量,条件队列的头节点和尾节点:

/** First node of condition queue. */
private transient Node firstWaiter;

/** Last node of condition queue. */
private transient Node lastWaiter;
1、核心方法:await() 不可中断的条件等待实现
public final void await() throws InterruptedException {
     //当前线程被中断则抛异常
     if (Thread.interrupted()) throw new InterruptedException();
     //添加进条件队列
     Node node = addConditionWaiter();
     //释放当前线程持有的锁
     int savedState = fullyRelease(node);
     int interruptMode = 0;
     //在这里一直查找创建的Node节点在不在Sync队列,不在就一直禁用当前线程
     while (!isOnSyncQueue(node)) {
         //park当前线程,直到唤醒
         LockSupport.park(this);
         //如被中断也跳出循环
         if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) 
         break;
     }
     //此时已被唤醒,获取之前被释放的锁,
     if (acquireQueued(node, savedState) && interruptMode != THROW_IE)   
       interruptMode = REINTERRUPT;
     //移除节点,释放内存
     if (node.nextWaiter != null) // clean up if cancelled
       unlinkCancelledWaiters();
     //被中断后的操作
     if (interruptMode != 0)
       reportInterruptAfterWait(interruptMode);
}

简而言之,await()方法其实就是为当前线程创建一个Node节点,加入到Condition队列并释放锁,之后就一直查看这个节点是否在Sync队列中了(signal()方法将它移到Sync队列),如果在的话就唤醒此线程,重新获取锁。此外,awaitNanos(long nanosTimeout) 方法和await(long time, TimeUnit unit) 方法的实现大同小异,只是在何时跳出while循环的时候加了一个超时罢了。
另外还有几个相关的方法也看一下:

/**
 *  添加一个Node节点到Condition队列中
 */
private Node addConditionWaiter() {
  Node t = lastWaiter;
  //如果尾节点被取消,就清理掉
  if (t != null && t.waitStatus != Node.CONDITION) {
      unlinkCancelledWaiters();
      t = lastWaiter;
  }
  //新建状态为的CONDITION节点,并添加在尾部
  Node node = new Node(Thread.currentThread(), Node.CONDITION);
  if (t == null)
      firstWaiter = node;
  else
      t.nextWaiter = node;
  lastWaiter = node;
  return node;
}
    /**
     *  释放当前线程的state,实际还是调用tryRelease方法
     */
   final int fullyRelease(Node node) {
       boolean failed = true;
       try {
           int savedState = getState();
           if (release(savedState)) {
               failed = false;
               return savedState;
           } else {
               throw new IllegalMonitorStateException();
           }
       } finally {
           if (failed)
               node.waitStatus = Node.CANCELLED;
       }
   }
    /**
     *  检查当前节点在不在Sync队列
     */
   final boolean isOnSyncQueue(Node node) {
       //如果当前节点状态为CONDITION,一定还在Condition队列
       //如果Sync队列的前置节点为null,则表明当前节点一定还在Condition队列
       if (node.waitStatus == Node.CONDITION || node.prev == null)
           return false;
       //有后继节点,也有前置节点,那么一定在Sync队列
       if (node.next != null) // If has successor, it must be on queue
           return true;

       //倒查Node节点,前置节点不能为null,第一个if已经做了判断,其前置节点为non-null,但是当前节点也不在Sync也是可能的,因为CAS操作将其加入队列也可能失败,所以我们需要从尾部开始遍历确保其在队列
       return findNodeFromTail(node);
   }
2、核心方法:signal() 将等待时间最长的线程(如果存在)从Condition队列中移动到拥有锁的Sync队列
   public final void signal() {
       //当前线程非独占线程,报非法监视器状态异常
       if (!isHeldExclusively())
           throw new IllegalMonitorStateException();
       //头节点是等待时间最长的节点
       Node first = firstWaiter;
       if (first != null)
           doSignal(first);
   }
   private void doSignal(Node first) {
         do {
             //如果头节点的下一节点为null,则将Condition的lastWaiter置为null
             if ( (firstWaiter = first.nextWaiter) == null)
                 lastWaiter = null;
             //将头结点的下一个节点设为null
             first.nextWaiter = null;
             //被唤醒并且头节点不为null则结束循环
         } while (!transferForSignal(first) &&
                  (first = firstWaiter) != null);
     }
   final boolean transferForSignal(Node node) {
       //如果无法改变节点状态,说明节点已经被唤醒
       if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
           return false;
       //将当前节点添加到Sync队列尾部,并设置前置节点的waitStatus为SIGNAL,表明后继有节点(可能)将被唤醒,如果取消或者设置waitStatus失败,会唤醒重新同步操作,这时候waitStatus是瞬时的,出现错误也是无妨的
       Node p = enq(node);
       int ws = p.waitStatus;
       if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
           LockSupport.unpark(node.thread);
       return true;
   }
3、核心方法:signalAll() 将所有线程从Condition队列移动到拥有锁的Sync队列中。
   public final void signalAll() {
       if (!isHeldExclusively())
           throw new IllegalMonitorStateException();
       Node first = firstWaiter;
       if (first != null)
           doSignalAll(first);
   }
    /**
     * 遍历所有节点,加入到拥有锁的Sync队列
     */
   private void doSignalAll(Node first) {
       lastWaiter = firstWaiter = null;
       do {
           Node next = first.nextWaiter;
           first.nextWaiter = null;
           transferForSignal(first);
           first = next;
       } while (first != null);
   }
作者:rickiyeat 发表于2017/11/26 15:13:31 原文链接
阅读:61 评论:0 查看评论

[bzoj3436][差分约束]小K的农场

$
0
0

Description

背景 小K是个特么喜欢玩MC的孩纸。。。 描述
小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得
一些含糊的信息(共m个),以下列三种形式描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多
多种植了c个单位的作物,农场a与农场b种植的作物数一样多。但是,由于小K的记忆有些偏差,所以他想要知道存
不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

Input

第一行包括两个整数n和m,分别表示农场数目和小K记忆中的信息的数目接下来m行:如果每行的第一个数是1,接
下来有三个整数a,b,c,表示农场a比农场b至少多种植了c个单位的作物如果每行第一个数是2,接下来有三个整数a
,b,c,表示农场a比农场b至多多种植了c个单位的作物如果每行第一个数是3,接下来有两个整数a,b,表示农场a
种植的数量与b一样。1<=n,m,a,b,c<=10000

Output

如果存在某种情况与小K的记忆吻合,输出”Yes”,否则输出”No”

Sample Input

3 3
3 1 2
1 1 3 1
2 2 3 2

Sample Output

Yes

HINT

样例解释
三个农场种植的数量可以为(2,2,1)

题解

差分约束一眼题
直接设d[i]为第i个农场种植的作物数
输入x,y,c(c第三种操作可以去掉)
第一种操作 d[y]≥d[x]-c 那么x~y连一条-c的边
第二种操作 d[x]≥d[y]+c 那么y~x连一条c的边
第三种操作 d[x]≥d[y] 且 d[y]≥d[x] 那么x~y和y~x都要一条权为0的边
跑最长路即可,最短路的话吧上面改一下也可以跑。。
记住判环的时候一定要break掉while

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
    int x,y,c,next;
}a[51000];int len,last[51000];
void ins(int x,int y,int c)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;
}
int d[51000];bool v[51000];
int sta[51000],top,ru[51000];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        int x,y,c,op;
        scanf("%d%d%d",&op,&x,&y);
        if(op==1 || op==2)scanf("%d",&c);
        if(op==1)ins(x,y,-c);
        else if(op==2)ins(y,x,c);
        else ins(y,x,0),ins(x,y,0);
    }
    memset(d,0,sizeof(d));
    memset(ru,0,sizeof(ru));
    top=0;memset(v,true,sizeof(v));
    for(int i=1;i<=n;i++)sta[++top]=i,ru[i]++;
    bool bk=false;
    while(top)
    {
        int x=sta[top--];
        v[x]=false;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(d[y]<d[x]+a[k].c)
            {
                d[y]=d[x]+a[k].c;
                ru[y]++;
                if(ru[y]>=n){bk=true;break;}
                if(v[y]==false)
                {
                    v[y]=true;
                    sta[++top]=y;
                }
            }
        }
        if(bk==true)break;//这里一定要break,因为上面那个break只是跳出if的。。 
    }
    if(bk==false)printf("Yes\n");
    else printf("No\n");
    return 0;
}
作者:Rose_max 发表于2017/11/26 15:34:09 原文链接
阅读:31 评论:0 查看评论

BZOJ2438: [中山市选2011]杀人游戏

$
0
0

Description

一位冷血的杀手潜入 Na-wiat,并假装成平民。警察希望能在 N 个人里面,查出谁是杀手。警察能够对每一个人
进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民。 假如查证的对象是杀
手, 杀手将会把警察干掉。现在警察掌握了每一个人认识谁。每一个人都有可能是杀手,可看作他们是杀手的概
率是相同的。问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少?
Input

第一行有两个整数 N,M。
接下来有 M 行,每行两个整数 x,y,表示 x 认识 y(y 不一定认识 x,例如胡锦涛同志) 。

Output

仅包含一行一个实数,保留小数点后面 6 位,表示最大概率。

Sample Input

5 4

1 2

1 3

1 4

1 5
Sample Output

0.800000

题目传送门

这道题细节是真TM的多….一眼看出tarjan缩点然后WA了一个小时
本来想着缩点之后直接问他有几个入度为零得点,那么答案=(n-入度为零)/n
但是WA了,才跑了几个数据
我不服,再想,AKCqhzdy跟我说,这道题很多细节,于是再想
如果ABC三个人,只有一个凶手,A认识B,那么就不用问C了。
为什么?因为只有一个凶手,问了A就知道了B,那么剩下的C就可以推断出来了
再改,改成如果这个scc只有一个人的话就不加上他了,结果又错了….
再改
一想,不对啊,一张图顶多只有一个点是这种情况啊,而且如果这个scc能问到其他scc并且被问到的scc只能被他问到就不能不问..
再改
于是就变成了询问有多少个入度为零的scc在判断是否有一个scc的tot等于1并且连出去的scc入度不为零,减去就好
至于时间复杂度…我懒得大改代码于是很暴力,跑了800ms

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm> 
using namespace std;
struct node
{
    int x,y,next;
}a[2100000];int len,last[2100000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int low[210000],dfn[210000];
int id,cnt,top;
bool v[210000];
int sta[210000],belong[210000],tot[2100000];
void dfs(int x)
{
    low[x]=dfn[x]=++id;
    v[x]=true;sta[++top]=x;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dfn[y]==-1)
        {
            dfs(y);
            low[x]=min(low[x],low[y]);
        }
        else
        {
            if(v[y]==true)low[x]=min(low[x],dfn[y]);
        }
    }
    if(low[x]==dfn[x])
    {
        cnt++;int i;
        do
        {
            tot[cnt]++;
            i=sta[top--];
            belong[i]=cnt;
            v[i]=false;
        }while(i!=x);
    }
}
int n,m;
int ru[2100000];
int main()
{
    int ans=0;
    scanf("%d%d",&n,&m);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ins(x,y);
    }
    top=id=cnt=0;
    memset(dfn,-1,sizeof(dfn));
    memset(v,false,sizeof(v));
    for(int i=1;i<=n;i++)
        if(dfn[i]==-1)
            dfs(i);
    int s=0;bool pd=true;
    for(int i=1;i<=len;i++)if(belong[a[i].x]!=belong[a[i].y])ru[belong[a[i].y]]++;
    for(int i=1;i<=cnt;i++)
        if(ru[i]==0)
        {
            if(pd==true&&tot[i]==1)
            {
                bool bk=true;
                for(int j=1;j<=len;j++)
                    if(belong[a[j].x]==i&&ru[belong[a[j].y]]==1)
                        bk=false;
                if(bk==true){pd=false;continue;}
            }
            ans++;

        }


    double sum;
    sum=(double)(n-ans)/(n);
    printf("%.6lf\n",sum);
    return 0;
}

by_lmy

作者:HeroDeathes 发表于2017/11/26 15:47:36 原文链接
阅读:28 评论:0 查看评论

LeetCode 分类练习(4)—— set 和 map 在解题中的应用

$
0
0

349. Intersection of Two Arrays

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2].

Note:
Each element in the result must be unique.
The result can be in any order.

给出两个数组,写一个功能来计算他们的交集

注意:在结果中每一个元素都是独一无二的,结果中的元素可以是任意顺序

package com.leetcode.array;

// 349. Intersection of Two Arrays

import java.util.*;

public class Intersection_of_Two_Arrays {
    public int[] intersection(int[] nums1, int[] nums2) {
        if (nums1.length == 0 || nums2.length == 0)
            return new int[0];

        Set<Integer> set_1 = new HashSet<>();
        for (int num : nums1)
            set_1.add(num);

        Set<Integer> set_2 = new HashSet<>();
        for (int num : nums2)
            if (set_1.contains(num))
                set_2.add(num);

        int[] result = new int[set_2.size()];
        int i = 0;
        for (Integer num : set_2)
            result[i++] = num;

        return result;
    }

    public static void main(String[] args) {
        int[] nums1 = {1, 2, 2, 1};
        int[] nums2 = {2, 2};

        int[] result = (new Intersection_of_Two_Arrays()).intersection(nums1, nums2);

        for (Integer num : result) {
            System.out.print(num + " ");
        }
    }

}

350. Intersection of Two Arrays II

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2].

Note:
Each element in the result should appear as many times as it shows in both arrays.
The result can be in any order.
Follow up:
What if the given array is already sorted? How would you optimize your algorithm?
What if nums1's size is small compared to nums2's size? Which algorithm is better?
What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?

给出两个数组,计算他们的交集。

注意:每个元素的出现次数应该和他们在数组中出现次数相同。结果可以是任意顺序的。

package com.leetcode.array;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Intersection_of_Two_Arrays_II {
    public int[] intersect(int[] nums1, int[] nums2) {
        if (nums1.length == 0 || nums2.length == 0)
            return new int[0];
        Map<Integer, Integer> map_1 = new HashMap<>();
        for (int num : nums1)
            map_1.put(num, map_1.getOrDefault(num, 0) + 1);

        List<Integer> list = new ArrayList<>();
        for (int num : nums2) {
            if (map_1.containsKey(num)){
                if (map_1.get(num) <= 0)
                    continue;
                list.add(num);
                map_1.put(num, map_1.get(num)-1);
            }
        }

        int[] result = new int[list.size()];
        int i = 0;
        for (Integer num:list)
            result[i++] = num;
        return result;
    }
//    public int[] intersect(int[] nums1, int[] nums2) {
//        if (nums1.length == 0 || nums2.length == 0)
//            return new int[0];
//
//        Map<Integer, Integer> map_1 = new HashMap<>();
//        for (int num : nums1)
//            map_1.put(num, map_1.getOrDefault(num, 0) + 1);
//
//        Map<Integer, Integer> map_2 = new HashMap<>();
//        for (int num : nums2)
//            map_2.put(num, map_2.getOrDefault(num, 0) + 1);
//
//        Map<Integer, Integer> map_3 = new HashMap<>();
//        for (Integer num : map_1.keySet())
//            if (map_2.containsKey(num))
//                map_3.put(num, Math.min(map_1.get(num), map_2.get(num)));
//        int size = 0;
//        for (Integer count : map_3.values())
//            size += count;
//
//        int[] result = new int[size];
//        int i = 0;
//        for (Integer num : map_3.keySet()) {
//            int count = map_3.get(num);
//            while (count != 0) {
//                result[i++] = num;
//                count--;
//            }
//        }
//
//        return result;
//
//    }

    public static void main(String[] args) {
        int[] nums1 = {1, 2, 2, 1, 3, 3, 4, 3, 2, 4, 2, 5, 3, 2, 1, 3, 2, 1, 2, 0};
        int[] nums2 = {2, 2, 3, 1, 32, 21, 1, 1, 1, 1, 3, 12};
        int[] result = (new Intersection_of_Two_Arrays_II()).intersect(nums1, nums2);
        for (int num : result)
            System.out.print(num + " ");
    }
}

242. Valid Anagram

Given two strings s and t, write a function to determine if t is an anagram of s.

For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.

Note:
You may assume the string contains only lowercase alphabets.

Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?

给出两个字符串s 和t,判断 t 是否是s 的一个字谜。(字谜指t与s中的字母出现次数相同,但出现顺序可能不同)

注意:你应该假定字符串只包含小写字母

package com.leetcode.String;

import java.util.HashMap;
import java.util.Map;

public class Valid_Anagram {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length())
            return false;
        if (s.length() == 0 && t.length() == 0)
            return true;

        Map<Character, Integer> map_1 = new HashMap<>();
        for (int i = 0; i < s.length(); i++)
            map_1.put(s.charAt(i), map_1.getOrDefault(s.charAt(i), 0) + 1);

        for (int i = 0; i < t.length(); i++)
            if (map_1.containsKey(t.charAt(i)))
                map_1.put(t.charAt(i), map_1.get(t.charAt(i)) - 1);
            else
                return false;

        for (Integer count : map_1.values())
            if (count != 0)
                return false;

        return true;
    }

    public static void main(String[] args) {
//        String s = "anagram";
//        String t =  "nagaram";
//        String s = "rat";
//        String t =  "car";

        String s = "";
        String t = "";
        boolean result = (new Valid_Anagram()).isAnagram(s, t);
        System.out.print(result + " ");
    }
}

202. Happy Number

Write an algorithm to determine if a number is "happy".

A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.

Example: 19 is a happy number

12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

思路:当某个结果出现不止一次时,将陷入无限的循环

package com.leetcode.number;

import java.util.HashSet;
import java.util.Set;

public class Happy_Number {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        int result = countSquare(n);
        while (true) {
            if (result == 1)
                return true;

            if (set.contains(result))   // 重复出现时则无限循环
                return false;
            else
                set.add(result);

            result = countSquare(result);
        }
    }

    public int countSquare(int n) {
        int result = 0;
        while (n != 0) {
            int temp = n % 10;
            n /= 10;
            result += temp*temp;
        }
        return result;
    }


//    public boolean isHappy(int n) {
//        String s = String.valueOf(n);
//        Set<Integer> set = new HashSet<>();
//        int result = countSquare(s);
//        while (true){
//            if (result == 1)
//                return true;
//
//            if (set.contains(result))
//                return false;
//            else
//                set.add(result);
//
//            s = String.valueOf(result);
//            result = countSquare(s);
//        }
//    }
//
//    public int countSquare(String s) {
//        int result = 0;
//        for (int i = 0; i < s.length(); i++){
//            result += Math.pow((int)s.charAt(i)-48, 2);
//        }
//        return result;
//    }


    public static void main(String[] args) {
        int n = 19;
        System.out.print((new Happy_Number()).isHappy(n));
    }
}

290. Word Pattern

Given a pattern and a string str, find if str follows the same pattern.

Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str.

Examples:
pattern = "abba", str = "dog cat cat dog" should return true.
pattern = "abba", str = "dog cat cat fish" should return false.
pattern = "aaaa", str = "dog cat cat dog" should return false.
pattern = "abba", str = "dog dog dog dog" should return false.
Notes:
You may assume pattern contains only lowercase letters, and str contains lowercase letters separated by a single space.

思路,将pattern 中的 char 和 str 中的单词分别作为 key 和 value 放入 map 中,若相同的 key 对应不同的 value 或是相同的 value 对应不同的 kay ,则返回 false

package com.leetcode.String;

import java.util.HashMap;
import java.util.Map;

public class Word_Pattern {
    public boolean wordPattern(String pattern, String str) {
        String[] str_arr = str.split(" ");

        if (pattern.length() != str_arr.length)
            return false;

        Map<Character, String> map = new HashMap<>();

        for (int i = 0; i < pattern.length(); i++) {
            if (map.containsKey(pattern.charAt(i))) // 在 map 中包含 pattern 的字符
                if (!map.get(pattern.charAt(i)).equals(str_arr[i])) // 但 pattern 中同一个字符
                                                                    // 以前 和 现在对应的 value 不同
                    return false;
            if (!map.containsKey(pattern.charAt(i)))    // 在 map 中不包含 pattern 的字符
                if (map.containsValue(str_arr[i]))  // 但 pattern 中不同的字符
                                                    // 却对应了相同的 value
                    return false;
            map.put(pattern.charAt(i), str_arr[i]);
        }

        return true;
    }


    public static void main(String[] args) {
        String str = "dog dog dog dog";
        String pattern = "abba";
        System.out.print((new Word_Pattern()).wordPattern(pattern, str));
    }

}

205. Isomorphic Strings

Given two strings s and t, determine if they are isomorphic.

Two strings are isomorphic if the characters in s can be replaced to get t.

All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.

For example,
Given "egg", "add", return true.

Given "foo", "bar", return false.

Given "paper", "title", return true.

Note:
You may assume both s and t have the same length.

与上一题思路相似

package com.leetcode.String;

import java.util.HashMap;
import java.util.Map;


// 205. Isomorphic Strings


public class Isomorphic_Strings {
    public boolean isIsomorphic(String s, String t) {
        if (s.length() != t.length())
            return false;

        Map<Character, Character> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++){
            if (!map.containsKey(s.charAt(i))){
                if (map.containsValue(t.charAt(i))) // 两个字符映射到了同一个字符
                    return false;
                map.put(s.charAt(i), t.charAt(i));
            }else {
                if (!map.get(s.charAt(i)).equals(t.charAt(i)))  // 同一个字符映射到了不同字符
                    return false;
            }
        }
        return true;
    }

    public static void main(String[] args){
//        String s = "egg";
//        String t = "add";

//        String s = "paper";
//        String t = "title";

        String s = "foo";
        String t = "bar";

        System.out.print((new Isomorphic_Strings()).isIsomorphic(s, t));
    }
}

451. Sort Characters By Frequency

Given a string, sort it in decreasing order based on the frequency of characters.

Input:
"tree"

Output:
"eert"

Explanation:
'e' appears twice while 'r' and 't' both appear once.
So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer.

思路,使用 map 统计字符的出现次数,使用 桶排序的思想进行排序

package com.leetcode.String;

// 451. Sort Characters By Frequency

import java.util.*;

public class Sort_Characters_By_Frequency {
    public String frequencySort(String s) {
        // 统计 s 中的字符出现的次数
        char[] ch_arr = s.toCharArray();
        Map<Character, Integer> map = new HashMap<>();
        for (char ch : ch_arr) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }

        // 桶排序 bucket
        List<Character>[] bucket = new List[s.length() + 1];
        for (Character ch : map.keySet()) {
            int count = map.get(ch);
            if (bucket[count] == null) {
                bucket[count] = new ArrayList<>();
            }
            bucket[count].add(ch);
        }

        // 构造返回结果的字符串
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = bucket.length - 1; i >= 0; i--) {
            if (bucket[i] != null) {
                int count;
                int list_size = bucket[i].size();
                while (list_size != 0) {
                    count = i;
                    while (count != 0) {
                        stringBuilder.append(bucket[i].get(list_size - 1));
                        count--;
                    }
                    list_size--;
                }
            }
        }
        return stringBuilder.toString();
    }

    // TLE
//    public String frequencySort(String s) {
//        if (s.length() == 0)
//            return "";
//
//        char[] ch_arr = s.toCharArray();
//
//        // 统计 s 中的字符出现的次数
//        Map<Character, Integer> map = new HashMap<>();
//        for (char ch : ch_arr) {
//            map.put(ch, map.getOrDefault(ch, 0) + 1);
//        }
//
//        Map<Character, Integer> result = sortByValue(map);  // 根据 value 对 map 进行排序
//
//        // 构造结果字符串
//        String result_str = "";
//        for (Map.Entry entry : result.entrySet()) {
//            int count = (int) entry.getValue();
//            while (count != 0) {
//                result_str += String.valueOf(entry.getKey());
//                count--;
//            }
//        }
//        return result_str;
//    }
//
//    public static <K, V extends Comparable<? super V>> Map<K, V>
//    sortByValue(Map<K, V> map) {
//        List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
//        Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
//            public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
//                return (o2.getValue()).compareTo(o1.getValue());
//            }
//        });
//
//        Map<K, V> result = new LinkedHashMap<K, V>();
//        for (Map.Entry<K, V> entry : list) {
//            result.put(entry.getKey(), entry.getValue());
//        }
//        return result;
//    }

    public static void main(String[] args) {
        String s = "Aabb";
//        String s = "BabBbBbBbbABBABBbAabbbABBaBbBabaabBbbBAAaaAbbAABaAbBBaAaaaaBABbaBbAAbBBbbABBaaBBbabAbBBAAbAbaaaBrBBaAaabAbbBbABabABaBabBBBBBaAbAaABaaaAAaAgAaAaBAbaBaBaBbbbBbABBBBaaaBbbbAbbbBaBBaAbBBbbaaaaaBbbaaAAbAABBABBaAAABBbbBbBbbBbaABBAAbBAbabbbabwBbbBArABaBBbabBaBabABABaabBBABBAabBAAaabbbbBAababAaBaaAaBbBbBAAbaBabBbabaBaaBbaabABAbbBbaBAbabABbbaAaBbAAAbBbaabBBAbbbABbaabAAAaaaBaBaaaBBABbBAbAAbaABaabbbbBBAabbbBABBbaABBAAAabaAbaBAbbaBaBbAbaAAbBaBAbAabBBbBsBabbbAaBbabAAaABAaBAAAbbaBaAbABABBBAbABABbbbBaaBaBAbABAbaaAbBbAABBbAbbAaBbabaBbABAAbAABbbAabAaAaBbBBbAAbBbaaaBAbABBbBBaCabBBabBAaBbBaAbbBAbbBaBAabBAababAaAbaAaabBBBABabaabBAAAabBAAAbBAbAaaaAbAaBaAbbAaABABBbBBAABAabaAAbBaBbAAaabbABBBABaBAabAbAAbBbAabAbaBbAbBAABAABAAAbBaaaaBabbaBABBaABbAabBaBAbAbbABAbaAAbaAAaBaabaBbBBbBABAABBABBaabBBbBBABAAaAAbbBbABBBbAabAbABbAAAbbAbABbbAbBAbabbbBBBBbAAabaabBABABaaAbaBBBBbbABbBbBABBaAbAaBBABBBabAABBBBBbBBabBaaBbaaBaBbaBbbAABbbAaaBBBbabaabBABABBBGabbBAbaBabAaAAabbbBaabBBbABBabBabbBbAbbAaBbAaAabBabBBbaBLaAbbAaaBaabAAabbABAAAAAbaAbaAabaAaAbaAbBbBAABbbbaBABbBBAbaaBBbaaAbbaAaaJAaAbAbbXBABAABABbbbBaAABaAAaaaabbbbBaABbaAbaAAbAaaBAaaAbbBaaBAabAbbAbBAbBaaaaaabBBaaabAaaAAaAaabBAaAaaAABbbaAAababBBBAABbAAbBBbAAaBAaABabaAAbABBbAAbBBbbBBBBAAaAbbBBAbaHbAaAbrBBAaBBbbabAbBaaaABAAAaABaBBbBbBBabBBBbBBBAbAaAaaBbAbABaabBbBBAAaaAAabAaaabbHAabABAbaBBBbBAaAabbbarbaBbbaAbaBAaBBAbbBaBbBABBAAbAbaABbABbBBAABaBBbBAAAbaaBAabBaBBaABAzBAbAAABBAAaabAaAaBAbABaABaBAbbAaBbbAbbbbbBaAABaaBbabbbBABbbAAAbBbBBBaBBbAaAbAaABaaAbbaaAabaABBaAabbbABBbAabBAabaabABBBBABbBBaabbAaababBAbabbBaaAAabBBBBbBBBbBAAAABaaBBBAAbAaAAAABaabbaaAAbAaABaaaBbaAAaABBAAbbBAaBBAAaBBBaaaAaBAaBAABbBBBAABAbBAababBAbABABbbbaBbABaaaBbbaaAABBBAbAbAAAabbBBAbBaBBaAAbBABaABVbAABbbAbBaBbbBBAAabbBbAabBbaabbbbaBaaBBBabbaBbaaABaAABaAaaBbbBAaABAbaBAAbBabBABAaAAabbaaaBaabbbbaAABaAbBabBAbBAaaABaaABBAaAbBbBBaAABBAaBBAbABAbAbBAAbBbBAAaABbAaaABaabAabAAbabAAaAaBAbBaBBBBBbaJaabBAaaaBBbPbaBAbabAaAABaAaBaaAABBAbbbAbbaBAbbaaAbaBaaAaabAbabAbAbbAAbbBbBBbbbaaaaaaabAbbBBaBbBaBAAAAbBAaAaaBBaBaBAbBBAaBAaABbbAAbAabBbABBBaaaBBabbAAbABBbBAbbbabBAaBAAAbAbABAaaAABbbAAABBbAabaBBBAaAaBBaBBaAAaaBaAbABbBbabbabaBBabbBBAbbaABBaBaaBbaabaAabBaBbAAAabbAABBAbaAaaBbAAabBAbAbbbBAbaBAaabBAabbAAaBBAaBBBBAabBBAAbbAaAAAaAbbaAbbBABbAbabbbAaAAABbbbBaaaBBAbbBABbbABAwBAbBbabABaaaaBaAABbABABAABaAabaaBbBBaaBbaBAABbAAaaABaBbAbBaaAAbAABbBabbABBaabAbbbAbBAbaBAABABbBABAbaAAbAbbBabABBAbbAaababbaBAAaBBABBaBABABAbaaBAbABbbBgaAAAbaaBaBbBAAABabaBbBAAbabaBBBbaABbAAaAaaaaAAbbBbaBaAbaBabaBBAbaaaAabbAAaaabeAbAbBaAAaaaAabbBAaBabABaaabbbAABbabbAaabaAAaabAabbaaabbBbAbBBABAbBbbABabAbABaaAAAbaBAAbabaEAAbBBABAabAbabAAaAaAaBaAaaBaaAAaaAbbbabaaAABabAaAAGaAbAABaBBabbaBAbAabAaAaBBAabkbBBBbAABabbABBaBbAbBbAaAAbbAaBAaBbABaababABBBabbaBBrBAbbaBBBBbBabBaABBabbZbbaBBBaBABaaAAbbAABbABBAABabAbbbbBBbBBbbAaaBaabABAaBBaBbAnABBBbbBBAabbbbbabBaaaBBBAbAabbABaBBAaAbBbbbAAABBbRAAAAABBabAAbaabbbAAbBAAaAbBabAAbAbaabAaAABbbaBAbaBbaaabBaBbBVAAAaABABaaabAAabbBAbAbABBbabaabaabBaaAbAbbbaaBbbbBAAabbbBAaabBBbAaABbAAaaBBbaAbaBAbABaaBbbBaBaaabbBbaaBbbBBbbAabBaaBabAbaBABAbAabbAAaABAbbBBbaBaBabBaabAAabaAbbBaBbBAABBABabBbbBABabAABabAaaabBbABbaAaAbaaBABbaAbBbbbbaBbabBaBAaAbaabAbbabaBBaaaaBaAaaaABBBaBBbaaBbAAbaabBbaBBbAbbAABBABAAhBaBAbAaaAaaabBbABAAABBAbaAbbBAabBBaaABababAbbbBBBAaAaBbAaaBabBAAAAaaBBBBaaABbBbbBaAbabAbaAbAaaAabbBaABAabbBAAAbBAaaBbAAbbbABaBBAaaBAABABaAaaBaaAABAbBBaABABaAbAABAbbAaAaAbAaBBAAbbbbaaabbaaBbbrXbaBbaBAABBBbabbbAaAabAaABBBbABAAABbbaBBAAbbBBbBAAABaabAbaAbababbabaBaAbAaaAAabaBBBBAaBAABaBAabAaaAaBABBBaBbbaaABBaAABBAaabBAbAAAbbAAAaabAaabbbBbBAbBBYbBBaGbaBaBabaAAaBBBABbaBaaaBajbBABBBAakbbBBaaaBbBaBAbbAAAbBaAaAAabBaaabbababaaabAaaBBAbbbabaBabbBBbBbAbBBAbaAbbAABbbBbaaBBbABBbbbbABAbbBBBABAIbAaBBaBaaBABAABArBAaAAAbbBAABabbAMBaaBBBBAAaBBAaabbbbbAabaGbaABBaaaBBBbaAbBBAaBaabAaabaabAaABAbBBAabaBBbBbBbBabbABaaABbabAbBAAbAabaaaaaaABabBbbbAbBBABaABAaBABABbaBbABBbAaBBAAabbBbaaabABAabaAaBBaAaaaAbbbabbbbBaABBAABbBbeBAbaabBbBABBBBBaABaABbbAbBAaabABBbBbbaaaabaaBaABbAAbbAaAaAabbbBbaBbbBAabABaBbBbBaBAaAAAAbABBAAbBAAAaABaAaAAbABBbAabbBAAQbabbABbAAbbBBBaaaaAaAbABAbaaBbAabBAAaAAaAbBaaBBBaaaBaabaabBaababBAABBaaABBbbAbAABBbBbbABBAaBbbABAAabbAcaAaBbBaBbBABABaAaAbBbaBAabBaaaAaaaAABABBaaaaaBABAaababbbabBbAAbbBaAdaAaAaaAaBAAabaaBBbBbaAaBbabaaBbBbBbBAbAaAaBABABABBbBAAAbbBBaaAbaAaAAaBabAlBBBAaBaBBaBobBBBAABaABBBABBaaBBaBaABBaBbaBBAbAaAbaBBBabababAbBbBaaBbBAAAaABBBAAAbBaBBbAbBBbaABABBBBaaAbabAbbbaBAbABBbAAbAbabBbabaAAAbBAjbBAbaBbBAbABAAbabAbaBAAaAaAbBBbaAbAAaBAbaaAAaaAbaBaaaBBBBbbaaBAaBBabBaabbbbbbaAAAbBBAaaaaaBBbaaAABBAaAbaBbabBBBaBBAbABbbBABabbABbabbBbbaabaBAaAabBAAbAaaabBaBabbbaaBBbaBaBBABAABBbbAABbaBbbAAaAaaaaaBbbAabBbaBaaabBAabBaBaFBAabBrabaBbaABbABbabAbaVaAAAabBbaBBAAAbbaBBaaABabaabAaaABBBbBAAaabaBbaBBBAaAaBAbAAbBBAAbAaBBababbaBABbbABBBABbbBAABAaBbbBBaabAbbBAaBbbabbaBBAAbabbaBBBbaBAaBaaBbbBBbbBbAabBBbbbaabAAAABaBbBBABbBaBBBAaaAabABBbbBbbabABbAbbbaaAaAAbaABaaAAaaAbbaBBAAbabBbababBaAaBBBbABbbBaaaBabaBaABbaBabBAAaZABAbbaAaaBbBAbbABbBBabbBABaBBababABaaaBABabaBAbaABBaAaBabbbABbabAAABAAAFaABBBBaAAbBbAAbbBAABaaAbAbabaBAaAAabABBAAAAbbBABaabbAaBaBbbABBbAAbAbbABABaBAabbAbaBBBbAbABABbbaBAbaaABAabaaabAbaAaabAbAABBABaBbBBbBbbAAbAbabAaaBbBbBbaBBabBbBBAAabbbZaaAbaAABBAaBaBbabbBBbbAbAaBBABABbbaAaaAaBBBbaalbbaBAbBaAABBbbBbaaBbabaaaAaAbAaAbAbBaBbaBbaAAAbBbAbbABBaaAAAApaaAbAALBbBbBaABbbbaAbBAbAbabAbAbbAbabaabBBbabAaaBBbaaaABAaAabBAbAaaBAABBBAAbBAaaBBABABaBbAbAabBBAAabAbbbbaBAAbBBabbaAAabAbBbAABBaBbBAAbaBBAABbbABAaAbAbabBAaabAbbAabBABaAABAaAaBbBBBbaaAbABBaAAbaaaAAabBBBAbaaBAabBBABbbAaaABbaabaAbBbABbbAbBAABbBbbBBbBAbbBBBBbBbaBAaBAABABbAAaaaBBBBAaabBAbbbbabaaaaBBabaBBAbAoBBBBbaBaAbAAbAaBaababBABbbBaabABaAaBBAaabBBaAABbbAabababbabbbABbbBabaabAbaBAaaaaBaabBbbAbbaAAbaAAabAABbaBaABABbaBAbaabBAaBaBBBBBABbaAAbbaAAAabbbgaBABBAbabbbaAabAaaAgBBaAaaABABBBabBaBabbaabaAAaAABaBBABAbbaabABBAAaAbAbabBabBaBbaABbBBABBaAaabbbbBBBaAbAAbABAaAABABbbABbabBabaBABAaBBbAaBBBBbbAbBBAaaBBBaBABaAAAaabBbaBbbbabbABaaaaBaaBAbABaBabAbBAaAbaAABBaabaaBBaBaaabBaAabABbBaabAbABBBbBbabBBbaAaBBUbBaBBabBBaBaabAAbBbaBBaBBAbAaBbAAaAaAbbbababBababAAaAAabaBaBaaBbBbBaBaaaABABbBBAbaBaABBABBBaBbaBABBBBbabBBAaBAaabbBbaabbaABBabbBbAabbaBAABaBaAABabAAbaaBbaAbabBBbBbaaABBAAAbAABaBaabaAAAAABaabAAaBbaaBAaAaaaAbBaAaaBaBaAAaaBABAAraBBAabBaABbaBaBBAaAABaAAaAAbaaabBABbAabABbBabBbbbBaaBABBBabaBBBaaBaABaaaBbabBAABbaaBBbABaaaAbaBbAAaAaaaaBaaBAAaAabbbBBqBbBaaBbaBBBBAAabbAbaVbaaBBbBabBbabbabAAaABaaaAABabBbbbBBaABabbabbABAaABaBaAAbBaAaAaaABabbaBBabaBAMBbBBABaAaAbbAbbAABBaABAaBAbBABbBABByaabbAbBABAAbBAabaaAbAabbbBaBbAbabAAbbAbbbbaAABabaAAAAaBabBBbAbaaaBaaaabMBBAbAbabAeAaBAbBaBababbADBaabABbAaAabAabBbaaaaAbbBBBaAABaBAbBBABABbbbAaBABAbbBBabBAbbBBBBAbBbbbAbAbaABaBDbBabBBBbAbaABababBbaBBBbbBBAAaAABBBABBaaBBBaAaBAaBbbbBBaBaaAbBbbAaBbaAaaABAaBbAAaABAbABAABabbbabBAaaBaBaAaabBAABAabaaAAbbyaabAbAaAaBaAaaabaAbBBAabaAAbbAbABbBbABABAaAabaaBabBabbabBabAbbaAbBbabbAbAaBaaaAaBBBBabbBbaabbabAaaBBabbABbaabbAabAabbBaBBBabaaAABbAbabbBABaBaAbbabbBBbBBbAAaAbbAaBbBbbBBaBAABBBaABAaAabaBaAABaAbaAaBbbbBbbBAaBBAAAaAaAaBAbBBBbabbABaAbWaaabAaBBBbAABBBAaBbAaababaLAbAaABAaBbbBBbbAaBbBAaAAbbAabaBabAAaABAbbaabxbbBababBBbbBbababBBaBabBbBbbBABBABABbbBBaAbBbABBBBABbBABAAaBBaaBBAAbbBBbBaBaAaBBaabBabBAbbAABbAABbAaAabbBbbBabbaAaBAaAaBbAbBbbBaBaAaBAbBAAaBBBaBbGAABAABaABaBBAbAAaAABABaBaAABbBaaABAbBaAABaBAbBAaBbaBbBbBaBABAaaBAAaaBBaABBABAaaaAbAbAABBBBBaABbBbBaBBbaBbABBAaBaBYaBaAbBAbaAaaBBbAbaABBbaABABaBaBAbbBAAAaBBaBaabAaaBBbbBbBBbBabBaaaAbAaBAbaBaBBbBAbBBBbabbbBAbbaaBAaabBbBAbAabbBBbbabbBAabbaaAbaabAAabbBAbABaaaaBbbababAaBBBbbabBAPAaaAbbaAAbAAaAbaBAAAbbABbabAAAABBbbBbbbABbBAaAbbaaBbBbAaaAaaBABaabBbaaBabABbABBBbBAbbBBPBBaAAaabAaaaBaaBbABAbbBaBAaBbAaaBabbaaBBBBBBbbbbbBBbAabbABAAbBAbBAabaAbBAbAaAbbbBAAAAbbbABBbaabaABaaAbBAbBaAbBaAbbbSAbaABbBAAABaABBBaaAbABbBBbbABBaAAbaBAaaABBBaabbBbABaaabAABBBABaAABaBbaaaaaAaBbBAaaBbAbABAABBabBbbAbbBaaAaBBaabbbaBBbbBbaIbbaAABBBBbAbBbaBAabAAaBaaAaAaaAAAAbABAaAABAbBBbaaabababaAAaBbBAbBbbBaaBaBBbbBaaaBABbBaAabBAabbAaBAAbbaaaabaBAbbabbBbBABbAbAAAAbbabaAbAbAaBaabbaaBaAaBbBAaaBABAAaAbIbaABAbBaabBBaBBABbABAbaBarBAabbBBABbbbAbAAAAbAAbBabbAAababAAAbBaaaABBAaAABbaBaAbabBabAaAAbBaAbBAAaAABAAbBaBBAAAabAabbAAaaaBBbaABAABBBBBaABAabABbbBbBbABBAaaBAabBBaaBAbBaaaAABbaaabaBaBbBaaAAabaABabAABabBBABaaBaAbbabaBaAaAAAaabAbAbbAAbaaBbAaaBBbbAbBBabbaabaaabbabbabbBBbbABaBaaAAaBBaaAbbbbabAAbbBaAABbBbbAbABAAaBbBbABaBABABABaAAABbABbaaaabBaABaAbbbbaAaABAAaAbAABbaaAabBabaBbbaaaabBAaAabBBaABbBbBbBbABBbAbBABbbabBAAaAaAaaBAAaAbaaBbBaBAbAAaabBBBAbbbaaBaabpBbAbAbAaaBbABaabBbaaBaBaaBbAbAaABAABBbAabaaAbabBbbbaBBaABaBaAbbbbBaBaAbaBBAbAAABIaaBBAaBbaBBrbaaAbabAbABaaABabAAaaABaabABBbAAbBbBAbbAbAbBbbbbbBbaAbbAAabbABaaAbBABBabaBaAAAbbBAbAABaaaABabbaabBaBBbbbbbbAAbABbbAabaaaaBBAaBABAaabbABAbABAABbBBbaABaBBBObaaababAbBbAbbbbbbbBaBAAaaBBAbAaAAbBABaAAaBbbbAaaBbBBabAAABBabbAabbaBaAAAaBBBbbBBbAbaBBAbBbabAAaaBaBbBbaAABaAbbBABbBBABbbAbbbAbbbbaaaAbbabAbabaBBaaaabAAAaAbBABABAaBBbbaabaABABaAAAaAABABBbBBBBAaAbBBBBAaAaaaaBbaAAbaaBBBaaaaBBBaBWAabaBbBBabaaBBAbaaAabBaaAAAabbaBABBaAaabbABabAbBBaAbaAbBabbbBABaBBABaabBbaAbBbbAaABaaBbbbAAabBbAAbaAAAaBbaBAAaABABbABbBAAAaAbBaABABbAaabBaBAaABABbBAAbabAbbAaBBBBabAabbABAaaABAbaaBaaABAAbaBabAbBBaBbBaAbaaBBaaabaabAaaBAAABbaaaaBAabBbAbbAaBaaaaaBBBbbabAbbBaBBAabBABbAbaAAABaBaaababbBBBbabbaBaABbABbBBBBBAABBAAAaAbBBAbaAabAbBBABABBaaaBbbbABabbBAAbAabaBAbAABAaaAabaBabaBbAAbBbbaaAAAFaBaaBABAAbabaaabBaaBAbAbBabABBaAAABaaAAABaAbBaBABAbpBBAbabAabBAaBAAAaBbaAaAPBAaAabbBAbaaaAbaBBbbABaaBbbaBAbaAABAabaAbabbbBaaBaaaBAAaaBBaABaaaBBaBbBBbBbbgbabbbBabAbaAbbAABBababBbbBAbAAabaBAaABbaAAAABbbEaaBabbBBbbaaAbBBaAABBbaAAaBBbabaaBaAabBAababbabbaaAbBABbAAbBbAabaBAAbBabSBAabaBaaabAbbaBaaBbBbAbBbBBBAaBBAbAAbABAbABbbAaABaRABbaBbbbaABbBbBAaBbBaBdBbabBBababAAABBaabBAaAbBAAbabBbabBBaBaABaaaAAaBaABABAbBaBabBBbbABBaAabaBbaBbbaaAaABAbbABBAbabaABAaABaAAaAababaABAABAbaBbbabaaBABbBbAaBAabbABBaabBAaBbabBaBAABbBAabaAAebAbaBaBbDBaAABAAaBbAAbABaAaAbBAbaaaAababaAaaUbBaBbABaABABaaaBbAaabBABaBAabaaaAABBAabbabBAbAAabBaABbaAaaaAbaABaBAaBBbBabaaaaaBAAaaBabbbAaBAAaaBaBBaAaabbBaBbABAbABaABBabbbBaabBBbBBBBABbAbabbaAbBbBBBBbbAAbAAbABBbbAbBBbAABBbbbaaAaAabbBBbAbbBBBBbAabaAbBBaaaaBbAAabBbbbaPABBaAAABabAAAaABbbAbBABBAwBbaAAAaBaAAAAAAAABBBBbBbbBaabBABABBABbAaaAabBbbbBbabaaBBBBBAabbABaAbbBBabAAbAAaaBAAbAaAAaBbABbBAbaaBbaBbbAABAaaaAAaABAbBabaABBaBBBaBbQaaBAbABBABBBaBbBLABBBbabbBbAbAAbaBaaBaaBBABbaBaABBbabbbaAaBBaBAbBAbAAbBbBAbBaAAybBBbaBbbbBAAABaAbAaBBbbABaabbabbAABbbBbAaAaaBbbABBAaAbbaBAbBaabAAAbbaAAbBBaBBABBbBBaAAaAAAabBBaAABbbBBabBaaaAbAaabbAbaabbAbBaBaaBBAbBaBAAAAAABbABaBAAaAaAaAAaabbaaAaAbbaaAabBbBbBabbAAaBoabAAaAasabAaAabBBBbABBABbabaAbABabBaabaABbbABaBbAABAAAaBebAAbAABabBabABbaBbaabAABbABabBAbBaAABbbAbAAABAaBAbaAAbaAAbaaAbaAABbaBbbBbAABAbbBaaAbbABBAbaAaabAabaAAbaBaaaAbAaBbaabaABbaBbbAbAABbBBBBAbbABBaBbaAbbaABbaaBABABbAaBbAABAAaBBBbBbAAbbaABBAAABbabABbBBABAAbbBAbaabBBABAabbaaabBBbBBBbbBbbAABaaaBAaaaaAAabAbAAbaaaBabAAaaabBbAbAcbAAaaaAAaBBbAbaAbabbBAaawABBBBAaBAbbBBAAABabaaAbBaAbabBbbBBAaaaaaAQbbAaBAaaBAAbAaBxBAaBBabBbBaAaBABaABABBABbBAbAbBbAaBabbAAAbbbBAbBBABabbAaAaaBBabBBbAAAAbaabbBbabBaAAAaAAabBaBaBbBBAabaBBaabBBBBBABbaaBbbAbbbaAbbbAbbBaAAbAbabaBaaAabBABAbbAaABBBaabbbbAaaaabAAbabAbbAbaBaAAAaBaaaBAAaaaAbbAAaABaAABHaAabAabABaAAababBbAbAbaAbbBbAAAAABaAAaAbbBAaABbBbBAAcbbAbBBbAbAaXaBAaBAAAAaAaaAabaAbaBBAABbabbbabbAbAaAbbabBbaabbBaaBBabAbAbbBBBBAbABBAABaAbbbbaBAabAabAaDbABAaBbBBaBBbBABBAaAbbaaAbBaaBbBBAaaabbaabbBbaBabBbBAAABBbbbBABbBAaBbBbbBabBabABAaBAAbaAbabBaaAABaJBBBABBBAbAbBABBBaaBaAAaSbaBAbaWaAAAabaBAAbAbAbbbaBbAaBABaAaaABAAabaBBBBBBAAaBbBbaaAbBbAAAbABabABaAbaABbBAbaabaaAbaaBbaaBaABAAaaAaBabaBBAaBBAaBaaAAABaBbBAAbBBBaababBABAaBbAbaaBaaBBAaAabbaABaaBbAaaaaBAaBAabbBBbBbBbAAAbbaAbbbBbBbAaaBbBaBBbAAaABbbBbabbAAbbAbaaaAAaABAaBaaabBAbbAaAAbaABAabBbBBBAAbbbbBbaaaaAbabbBBBAbABBaaAbaAAabaBAbAaaBaBaAAABaBbabBbBAbAAAbaBaAbabaasbabaaAbaaabbaBBaaBABBAaabBbbAaaaABAAAaBabaAAabbBaBBBBaabbAbaABbBbAbAabbAbaBabBabBAaAbbaBaAAbabbBAaaAaaBaBAaAaBaAAbabAAAAabBbAaBAbABAbaABbABbBAABBAbBABaabAAaBAabABaaBBbbbbabAAabABAbBabaABbabaaBAabBAAbAabBbbABAbBAaAbaAAbAaabbAbbAABAABbaBaAbbbabBAaaaabbBBBaBaBbAabABabBBbBABbabAbAaaAbaAAbaAbBaaBbABbbaAbBABBABBBBbbaBbbAAbBaAAAaAaaaAaAAAaBBBBaaaABBBBABabaBAaBAAaBBbaaaBbAbAabaBbABAbaBbAAABAAabbBAaabBababbAbBAAbabbaBbBaBaAbbABabBBaaabAABAAAAAbbbbBBBBAAAaaBABbBAbaAAABBBBBAabaAbBBbBbaaBbaBBbbAAabaAbBAAAbBBbAAAABAabBaAabBAabbabbaaaaBaabBBaaaaAAAaAABABbbAaBbabbaAbaAAbBABbBaBbaAAAaBbBbBaabBbBaAAabaBaBBaaBAABaaaBBBaaAABBabbbbBbaBaBbBAaBBbbbAAaBaABBaBbbBAabBABABBBAAbAAaBaBBAaBBaABbbbaBaAaaAaAABaaAAaAAbBBabABBaaBBBABbAAAAabAbbaABbbbBBAbaaBbAAAAaAbABbabAaABbbbBbBAabbAaAAbAbbbbaAaaBaBbbBBAAaBaabAAbBbaAaAAaABaBAAaAAaaBAbbAAaaBbbabaaAAAAAaAbBbBAaBabaAbbABbBabBAAaaAbbABbaBnbBabtbBAbabBAaBaBABAbaaaaaAAaBbBBbaAbaBbbbAABBaBbBBAaBAABbBBAabBABAaBAbaBAaaBbBBAAbbababAAAAababaBAaAAbBBAAaaabbbbAaaaAbAbbbAabAaaaAAbaabaaaaBAbAaababbBbBBaABBBbBBBabaabaBaAAbAaBaAAabABBabAaBBbAAbbaaBbbbBbaBBaaaBAaAAaAabbbaABAbbbbabAAABbBBBBBbbAABBAaAaAabBABabbAAbbAabABAAaBbABbbbAaBABbABaAbbABaAaabBbABAAabAbaAaaAbAaaBBaabbaabbbBaaaABBbAababbBaBBaBABbBABABbbAaaaAbbBBABaAbAabbaAbbABaaBbBcaBbAbaabAABAbBaBbBaABbABBBbBbbababaAbabBABAAaabbAbABAbaaABbBbbBbbBAbbBbAAbbAaaaBbabAAABaBBbBAaBAbBaBAabBAAbbaBAABbbBbbBAAaBbBbBaBaabAakBBBaaBaaaaaaQabbbABaBbAaaAAAAbAabAbaBaaAaaAAbbaaaaAAbAAaAbbaaBaAaabbbAbBBaBABAABAbBBaBaAbaAAaaANbBAbxAaBbAbaABBbBBaabAABABBaBAbABAbaaBBaaBbAABbbbbAABBaabABaABAaBABBBABBbBABBABbABBAaaABbBBBBBbbbBabbAABBAAaaBBaAaABAbBBaBbBBBaAbaBBBBBbaABBAaABBBbbbBabaaBBAAaaABbBbbAbBBBbaAAAabbabAAaABbaAbbBbaaABAbBaaBbaAaAbbabaBABBBbbbbAbHBaBabaAabAbbBbbbbaBBaAABBBbAaAABABAABaAAAaAaBbAABBAbBbaBAaaAABAbBBABbAaBabbaABAABabABAAABaAaBAaAaABababbbBABBbaBBbBbaAbABbBbaABbAbaaaaBbBBNbBABABAAaBabBBBBbBBaBbAbabaabAbApAbabbaAbbAabABABBBBAABBAABaBbAaABbABBBbaBbbBAbBBaABBAabAbABBBaBAABBBbBaBBbBBBbAbaBBAbbAbbabbBBbaBabAdBbbbbabBABAbBBAAbBBAAaaBaaAbbbBaabAaABbabBbaaBAbbaAbbBbbbabABabababBaBbbBBabbAbBBbbbBbBBaBBAAbAabBAABaaaBBaabbABBaBaAabBbAbabbabaabBbBAABaabaAbBbbaabBbBABbABaBaBABaAaBBaBbaabAAAAbBBaAAAbAbbAABtABaKBBAaabbaabbAaBaBAABABAbABBBbbBAbabAAbbbBaaAbABBAAaaABbbaAAbbAbbaAbbaaaBABbbBBaaBbabAAbBbBbBAAAbbBBABbaBAAaAaBAAbaAAAABbbAbbabhbaBbabBbBBaBaBbAaBbabAABAbAAabbAbaAAaabaABaaBbaAbAAbaaBAbABAbABAabABaAbaBbABBbBaBaAaBAbaBBbAAaBbAAbAAAABBbAaBABaaAABAABAbBbBaAAbBaAAaaAABbBBABBBBaABBAAAbABaAaBaabaaaabbbBbBaBbAAABBAAbbbBbbBbAbAAbBBaBxBebbaaAAbBAbBAbAbbAaaabAbaanabaaabBAbBaAAbBBBbBaaAAbbBAaAaBaabAbaaAAABBbbbAAabaaAbabaaAaAABabaBaBAAbbbBabBabbbAAaabbaBbbbaBBbbBaBAAAAbBabaBabbbbaaaBbbaBABbaBAaABABBaBBAbavaaBbbaaaAAAabbaBAAaBABBBaBABzaaBabABaabBaAbbBABBbAAbbAAaAAbbAaBbAABBaBBaBAbAbaAaBAAAaBabAABBaaBBABAaAAAbbbBBaAaAbbbABBAbbABAbBbAAbbAAbBBbAAAaAABbbaBAabaaaAababBAbBbAIBaaaAbBAAaBbAaabbAbbaAaABaaBbbBABBBBBAAbBBbBbbAbABBBABaBABAbBaabaBabBAAbBBabABbAaabaBbBABbbbBaAbBbAaAAbAAbABbBbBaAaBbaaaabBbAaBBAAbAbBBaBBAaabaabbAbBabAbaABAbabBAbaBBaaIAAaBBaABbbAbbBAABbBaabaAabBAABABAaBBAbAbAaABabBbBabbAbaaaaaBbaaBBbaAAbABBbbaAABbbbAbAAbABBbABbBbbbaaabAaAaBBabBaBAaAZBbbaAAABAbABBBaABBbBaBaABAaaBBabABBbABbaaaAaBABAabaAABbbbbabBAbbAAAbBAbbAbaABbABAAbaABAbaabaBBabBaABabbaBbbbBAaaAAabBbAaabBAbbBBABbaBbBAAAaAbAAbBBABabBaBbaAAaBaAAaAAABAaBAAAbaabaBaaBaBaBbaBAabbaaUAbaabABbaaAbAAABBAakbAAAbbAbBabbbbaaABAaaaaaXAbabbaABBaaAABAaBBABbABaBaaAbbbabBabaaAabbabAABBsAAABBbBBaabBBaAbbaBbBBbABAbBaBBBaAAAAaABBBababBBbbbAABAaaaBBbbABAbbbAaaAAabBBbbAbBBAaaBabAabaaaabbAbababbABbBaBBabbAabaBBAbBBAbAbBBAabABBabAAabBAbBBaBAbbaAbAabbBaAAABbaAaAaBaAAAABABaBAaaAabAaaBAaaAbbaBaaBababbbAabaabABbbaBbabbbBBbBBAbaBaAAbaAabBAbAaAbaaAaAAAaaAbBaBbABBbaaBBAAABaABBbBAabnaABbBAbaBAAABABaBABAbaAAbaBaaAABbBaBBBbBABaBaaqAbbAaaBbaAbbbbBAAbbbBBAAbbaaAABBbBaabbAbAAbaaaBBAbabbBbaaBAaAbAaAbAABBbAAAaAabaAcAABAAbBabAbBaabABBbAabbBaBaBbAaaABaaBabaAABbbaabbBBBAbaBbBabBABbbABabABabaABaAbdaAbbaAabaBBABAaBBabbbaaBaabbBBABabABAbABBaAAbbAabaBbbBaaBbbbbaAAbAASabAbaAbABBbBABbBbbaABABAaBAbbbaAbaABAbbbaABABaabAAAbaabBbBAbbBbAbaBbaAaBaBaAAAaaaABaaAAaABAaaabAbBbAaAbABbBabBBAbbbbAABaAAABbBbAAaBBabBaAbbAAAABBABAbBaBAABBBaababbAAAAaBaaBAABAbBABBabBaaBABaBABaBaaaaBaBAbbabBbBBbBBaBaaBbAaBabaBaBaabbaBbABbBAAabBbBAbDBaBaAAAbaBaaABBBBaBbabbvBBaobAbAbmABaaabABbbaAbaababBAAbAAAbBbABBbAbaaBAABAAbBbBbBaBbAbaBAbbabaaBbAAbbbbAAAaAbbABABbAbBAbaBBAaBAAaBBaAbbbAbbBabbbABbaAbbBAaBaABabBaBABaAaabBAABBBbbbbBBBbBbaAabbaAbBbBbbbBbbbbaABAAbbaBaABAaaaaAaBbbBBaBbbbBaaaaBBbbaABABaaaABBBbabbBbbBBBbAAAaBBaabAbbBBabBbaAABBbbAbBbbAAAbaAbaaaabBbBaBBaaBAAABababaBBbbaaBBAAbBbbRbaBAaABBbBBBbAbAbbBbBABaAaAbAbbabbBBbbABAaABbaAabABaaBBbAaAaBBBBbABAbBaabaBBbABbbaAaABBAaBbAAbaBbBABbAabaAbbbABabBABABbbbBabBaBBbabBaaaABbaAAbBaaaaAaBbbAaabaBbbBBaBABbABBABABbaabBabaabBAAaBbABBAabAAaAkBabAAaaAabAbBaaaafaAAaBBBBaaBbAaBbaAbBAabaBBbaaABVaBaabAAAAaaABBBbaAAAaaaBBbbAaaaAaabaBbAbbBbBaaBBAbBabbBBAAAbabaAaaBbAaAAbBaAbAaaBaaBbaAaaAABbaABBBBaaAaBABaaAAaBaBBAABabaAbAaAAAbAbbAABaBAAAbbbavbABAAbbaBAaBBabAaaaabAaBbAbABBabAAaAAfabABBABaaabBBBAbBBaBAabBBbbbBaBbbBAAbbBAaaaBAababBAAaBBAaBBaAbbBBaAbABAabbaAaBbabbaabBaaaaUBaBABAabaBBAABABAaBBBBAAABBAAabbBBbaAaBbAAABbbaaBbbBaAABAbAbAabbAbaaBbAaBbAbabbAAbABbbaBaAbbaAbbBaaAbbBBBbAAaAAaAbbaBaBaAbbbBaqBBAaAabBbBbAbbBBAaAAAaBBaBAAAAaaabBABbaBAbABAABBabbbBBBABbAaaAbabbabAbBBbABABBbAAAABbbAaabbAAAAAabBaaABAaAAaaBBabBaaABbBBbBBBAabABbAAAABaAAbBbBbaAbaAAABBAaAabbAABAAaBBaababABbabaaabaBaBAaBbABbBFBaABabaabBbAABAbBbbBABbbaaBaBaAbbAAaBaABBbbbBaBbbAAsAAaAAAaABbaAAaabaBAbbaAbbBBAaabbAabbBAabAAbBaAbbaAaabaBAbAbBBbBAaaaaAabAbaabbBbBbAABababAaaAaBBBABBbbBBBBaABaABBAaaABBAabBAAbAABbAaAaabBbAAAbbAaaaABAbaAaABaAbBaAaBBBAabbaaBRbaabBBAAaBAABaBabAObAbaaaAAabaabBBbABBBBAbbBaBbBAbbBBbBABbaaaBabbbabBbbbbAaAbBBabbaaaaaBabbAaBaBAbaAabbbBBAaAAbBaBbAbbAaaBaBbAbBAbbbAAABaaAaaaAaABBBAaaBBbABBABbbbBAbbaaAABBAAbAaAabAABBAAbaAAaBbBbaBBaAabbaAAAbAAabbAAabbBbBAababABAbaabABabbBBBbAAabaaaAabAbaABAaBAaABAbbABaBAbAbBAbaBqAbbaBBbBAABbAbbabbAaaAABAaBBaaBbBaAABbAaBbBaaAbaBaABAABbABAaBaBabaaaaasAAAAAaaAbbABABAabaAaAaaBBBBbAbbAbaBaaAAAbBABAbAABBabaaBbAbbbabbAaBBBABBABBBaAAbbBAAaAAAbABaBBbFBAabAaaAAaAabBbbAABBaabbbAAbBAbBAaBAbaaBBBbAAbaBBBbBbbAAaaaABabAabaAbBaaBBAbaAbbaaAABaBBBBAbAaBbaIABbBAaBaaBAAGaBAbeBBbaAAbAaAbAaBBbBBBbAbbaBbBbAbbbAAaBbBAbABbAaBAAbabBbbBAABAaBAabBBBbBaBAaBbBbzBBAAbBaAaBBbBaAAaBAbbAAabBaAaaAbAbbaaAaAABaaBaAAbaaAbaBabbBAaABAaBaaaBaAABbaBbaAabBABBbBBBBaaAabBabAABaBbabABAbbABbBaABAABAAaAbABAbaBbAaaBbAbaBAbAbBbaBbBAbaaaABabaabBaaaBbAAbBbaBBAABbAbaaabAAAaAabBBaaBabbaBBBabbabbAABaaAAaabBBabAabABAAAbBBAAAaabAAAAaabbBbabBaAbbBbBAbaBBbBAbbaAAbAABaBBBbabbbbbaabbBAbAAAAabaaaaBababaBbBbbAaBAaBaaaBbbbaBAbAAbWbAbaAaaABABbBbbabBaabAVABbBbbAbBBABaAbaAaaaBBABbAAAaaaBAAABaBaABbBbaABaABbABBBaabaAAbBbaAAaaabbAAAbAabbaaaAAABAAaabAABBBbaaabAABAbyBbBAaAbBBBBBbAaAbAbBAABAaAAaaBaAbABBbAAABABBabAbaBABBAAaABBbbbBABAbaABBbbAAaaaAbbaAbBpaAAAAabBabbaaBbbABBAAbABaBaAAbAAaaabbABABBaABBbAAaaBAAAbBaBBbAababaaABAABABBbABaBABbbaBAaABAbAbbabbAAaBabbaAbbbbBBaAaBAAaBbABbAAAAAbbbbAabbbBBaAAAAababbABAaabaAbBAbbAabbaABaAbbaAaAAbAbaAAbBABBBaawABBBabAABaaaaAABaBabAbAuAAAAAAAabBabABaBDAAaAaababBbaaBAAabBabBBaabaBbaaBbbAAbaBaBbAAbbbaaAbbaaBbBaAabaaaBBBABaaBAbABBaBbabbaabbBaaabBaAaBbABaBBAaaBbBaBabbabaBaAbaaAAbABbAbaBabaAAbAbaCaaaaAaaBABbbaBABAAaaaabBbbBaaAbbaBbAABAbaBAaBAaABAAbBabrBBBBaAabAabAabaBAaBBABbABAaaBbaABbBAbbAbbABAbbBABaaABbABAbAbbBabAabbbaaabaAABbAABabbbbaAaaaBBbAaAbBABAbBaABABDabAbAAbbbbBBbAaAABBaAababaABaaaBbbABAabbBBbAAaBAABBabBAaBabAAaBbBaBAaaABbBBABaaaabaBBBABBabBbABbaAAbAAABaBBaAaaBaABBabbBBbabbABaabBaBAaaaAabAbBBABBbabaBbaABaaAAABBBAbBAbaBbABBBbbaaABAabaABAABAaBBaAaABBBAAAbAaabBAbabaBBAabAbbabBBBaaaBBaabBabbaaAaBAAabbBaAaabaBaABAaBAaaBBbbbbAAAabAabdAbaBBABAAbaAaAAbAaAAbAAaAAABaBaBBAbBbBaBABBAaaaBABaBABjbbABBaBaBBAAabBABBaAabbbAaBBbaABbBbabAaAbBbaBaBbbABBaaakaAAbAbbaaBbbabBbbaaBAABAbBAbaBBbbBbABAaAABbaboaBBAAbaBbaBbbbaaBabbbabaAbABbBABBBaBBaABBaBAbbbAAAbAAaBAABAAbaaBbaaaBAbbaBBaAaabBbaAAAbbaADBaBAbAABbBAABaAaaaABbBaaaAABBAbBAbbBaABABbaBbbaaaBAaBBbBaaBaAaABabBaAaABAbBBbBABBbaBAAaaabBbbaAAAbBBAabABbBBAbbbBaBAabAbBbbBABBBaaaaabBAbaBaaaABBBAaabbBABABbAAbabAbabbBabbbAbaAaBBBaaBBbBBBaBABBabABAaBbBABBabbbbbaAABbAaaabaBBbBbBAAbbBaBabbBBbaaaQBaABBbAaaBBABBAaaBABbBbaaBBaaabbBabAbAaBbbAaAaBabAAbbBabbAaaaabBbabAbabBbBBAaBABAABBbbaabAbaBbbAaOAbAbAbABBAbaBbbaaBBABbbbABbABAAbABfaBABBAbAbbAAbAabbbbBAaBAbbaBBbAAAaBBAaaaaAbaBbbbAAaAaBaAaaAbbBAABBBBAbBBBAaBaBaBaAbbbAbaaaBbBWbBaBABaAbbaBbbabbbbbbaAAaAaaabAaBAAaaaAAbAABbaabbBbbbAbABaaABAAAAABbaaAaBBbaaaBbabBBabbBaBBaAbAbbbBAAbBBAbAAbaBBbABBAAAbBaaAAbABabAbbbbaBabaBAbbABaAABaBAABAaAAABaBBaBBaAabbBBbAaAAbABBbABAbBbABaAaABbAbBbbaBAaAAbABBBAaBbBbabABAaaAAbBbBbABbaaBAAAaAbbaaabABBBAbBaBAaaaBBaABbBaaababbAbbBbabaBAAbAabBBaBbbabBaabBABAaBaAbaBBBbAAbBbaABabaabAabAbaabBbbbABbabbaBAABBaBbabaBaBABAABAAaAFBABbAaABbABBbabBBBBaBbBAababaBaBbBabAbaBbAbaaaAbbAbaabbbbbaABBaBABABBaAAbaaBAABABAAaAaABaaBaAAAaBaabAabBBbbAbBBAaAAbaAabBBAbbaaAAaAaAAAAABABbBbAABaAaABraAbAaAAaBABBbAAAbABAbBbaBaaBbaAAbaBbBAABbBABbBbabABbAaaBAaaABbAbAaBbBaBBBaabAaAAbABaBabaBBBBBaABbBABbBbaBBBbBBBAbbabAAbbBbABBbAABabBAAaBaBbAAbBAABAAbabBzbbaaaAAaBBAbBbbaaAbWABabBABAbaBbabAaBAbBAbABAbaBaABBBBAbbAaaBBbABAaBbBAbbBBbBbaaBaBABBABababABaAbABBAAgABABaabBbaBaBbABBaAababBbaAbBbABBAABBBaBaABaaBAabaABBbbbbBABAaAbaAaaAAaabBBabAbbBABabBabaBBaABBbabbabABbaAABAbbAAAAbAbaBAbBbbabbaaAaBABAaaabBbBbAbBbaBaaBaAaBbABBBaaabABaAaabAaAAAABabbaaBaBBaaaBAbbBaBabbaBabbabAAbBaAbAaAAabaAAbaAaABAabBabaAbBBbBaabbAAaabABbAAABBAbaBBaBaBbbBABaBabBaaBBbBbAaBBAAaaBBBbAABaABabABaaAaaAAbBaAAbBbaAbAAZAAbaABABaAaAABAbABaaBaaBBBAaaBAbAaBBaAAaAaBBAABaBBbbBbABbaBbaBbbaAaaBBAAABbBBBaababbabBbbbAbBaababbABAbbBabbBbAbaBBBaaaBBbaabAaBaaaAaAaBBAbBaaBBBbAaaaaBababABAbbaAaaaBAabBaaaBBbBABbaaAABBbaababAaABbAbaabbAbabBabbAaAAAbBaBAbaBAAAbbaBBAbBBBbabAabbBABAbAAabAaBBbAaBaaabBAAaaBbabbbaAAaAbaababABbaAAbbbaBAbbBaAAaBBabbBAbbaABAAaAAABbaBbAbabBbBbBaAaAaaBAAAaAbBAaABbABAAAbbAAbBBAbaAbbABBaAABbAbaaaAAAaBaAaaBbBarAABaBbbBaBAAbAbAbbbBBBBBaAAbBaAaAAAaAAAbbAAbaBBaaBAbAABBAbbaBbbaBaBbaaabBBBaABaaabBaabaAAABBbAbbbABBabbbABAAAAAbbABbBAABaABbaBBBBbBBbBAAbrabBBaaAbAaABbbAabaBAAbAabAaBaaABABBAbbABABaBAbBBbbbbbbbaaBabAAaAbbbBaBaABbbbaBaABBbaBAbbABBBAbaAbbaabbbbbAaAbbaBBbbAabBbAabaBAnAbBaBBABAABbbABAabbBBAaabbAaBbBaBbBaBBBaAaABbaABAababbababaaaabBAaaaabaAabbBbBBbAAabbaAaABbbabaaABABaAbabaBbBBBaAbBAbbbaaBBbAaABbBbbaBAabABabAbabBbaBBaBaabBAbabaaaBaAaBAABBBbAABBAabbBABAabbaBABabBBAbBaBbaBbabABABbBbaAAaBaBaAbaAAbBBaabBABAbBBBBaabAbBBBABBAaabABbAAABBbbBBBbBabaABaBAbABaBbBbBaaBAAbabbBAAaABAAaaBaAbAAaBBAbBabaBBbAAaAaababAbBBAAAABabBaababAABBAubabaaBAAbBabABbBABAAAbABBBbaAABBBAAaBabbaBBBaaaaBBBbbbBBBbABAbBbbBaaaaabABBAAaaaBABBbBbbBBBABaaAbbaBaaBAbBAAAaBabbbAbaBABBAbBAbaabbAAbbabBaaaBBAABBaAABAbBaBbBabaBBBabAbaaaaabAaaABABBaBaaaabBBaaAAAaAbBAABbBaBBBabbBBAbBbAbAAAAbBBbBabBaaBaBbbBabbBBaABBABBAaaabAbbablaAABbaBbAaaABaaBBaBbBBAAaAAbBbbaAAAbAaBabBaAABAABBAbaBABAaAAABabaBbBABAaabAaBaAABAabaabbbbbbbbbBAAAbaAAbbbabAaABBBbAabBABbbAAaBBbABaBbaaaaAaaBabaBbaaABbAaBABBAABaaABbaBABaBbBBbaAAbaaAAabAabbaBbBBbABbBAbaaAabbbAAAAAbabBaAAabAbBaBbaAaaAABBabBAbAAbbBabBaaBbbBAabbBaBbbaBaaAABAABBBbbABbaaBbbaABafBaBaBAaaaaBbAAbaABBbAbBbBbaBaBbaBaabBbabABaBBBbBbbbabABaABBBBBbBaAbBbbAAAbBAaBbAAAABabAaaaAbaaABABBAabBAabbbBabaaABaaAaABAaABbabBaaAaBbBaaabAbbbbbabaBBaabaaBaaBaAbAAbababBbABaaabABaaAbAbbBAaAaAaAAbAbBBBBbbBaBbAaAbvBBABBtBBAAABBbbabBAbaaAbAABABbBaaaEAAbabbaaabbGAAabABBAAAAAbbbAbbbbbbBbBaBaBBbaBbbBaBbbaAaBaAaaBBaaBAAaBBaaaabAAaAaBBAaBbBAabBABABBABBaAAJbabbaaabBBBbbBTbAbbAbAABBBAABBAbaaAbAaAAABABabbaaaBAAbaaaBbBBABbabbaaAbbaBBbbAAAAaBAaaABbaAAaAbBaaAbbaAAbBaAaBBaBbBbBbbbBaAbBBaBaAABBaBBHbAbaababBababABabaBBaAAabaaAaABaBaaABaABBBbBbaBabABbbAABbaBabbBAabAbaAbbaBbBBAbaAaaabBaAAaAbBaAbbAAArBBBAbaAbAAAbBbAabBbAAbAbBABaAbBbbAaaabAAaBbABBbAAAABaBMAAbbaAbBBAbbAabABbbAbBbaBbABAUAaAAabBZBBbbbBabBbbBaAaABAAbbAAbaAbbAaabbaBbbAbAaabAAbbBtBbabbbbBAAAAAaaBbBAAAabLabBBaBbaabABbaAbaBABaBAAABAAaaBaAbaBBABaAbBbaabaaBBbabaABAaBbabBAAbbAaAaaAaBaabBBbaAaAAabBbBBABBbBBabBAAAbBaAbBaaBBbbabBbbAbAAAaaBaAbbAAAabaaBAaBaBAbaaBAbaaBbbABABABabBBBbABBaDaAAaBABABAAaAAAaABBBAabaABaababBaBaBBbAaaBAbbAABaaaaaAaBBaBbbabbBabaBBBbbBBBABbbaXbABAbBbABbBAbAbBabBbAaAababBaaABBAaAaabBAbaAbAbAaaAAabaaBbBbBBBBBBaAbbBBAaBBBBbbBABaBAabBbAbabAbaAaaBBbBaabBABbbBBaBBbAabBabBaabbBabbBAaaAabbBbabbabBBaBbbABAaabBAaAbAAbAAAaBbAAaAbaAAabAbabaAAAbBAbBbBbBaaAbabaBAAAaBabAaBBaaAbbbAaAAAbCbaABaBaAaBbAbAABaaABbAbbbaaABAaAabBabBBbBAaAABbabaABAlbBBABbBAbAbAbbAABBbbbaAaabbBAbAbbbabbAaABBBabXaAbaAAbBBAAABaaAAAABBBaAAabbbbbbbabaaBaaBAABBAbDABbbBBaabABbABbbaaBBBAAAAaabAaBAAabbBBbBaaBbBabAaBaaabABbbAAaBbAbAABAbABababbBbBBABaabBBBbababAabAbABbBAABAaaAaAaBBaBbBabBBaAbAAAAaAABEbbABBBbaABAaAAbaabBBaaBAbAbAbAbbAbAbBaBabAAbaABaAaAaBABbbABBAabBBaaaAaaaaAbAabbABbAbaBabaaAABBAbBBabaABgBBBAAabbbBbBBAbbaAbbabbABABBBAabAbbABAaBaaBBaABABbAaBbbBABbAbABaaABBbAaBbbABABBABaBaBAAABabbbAabBaaBarBBAaAAaBBaABABBbBAAAbaBbaaBAAabBabAAbAaaaBbaABgbBBabAbBBAabBBABAAAAbaBBbbaaAbBBBBaaaaAabBBaBBbbbBaABaaAbBBAabBbBBbaAAaAaBaabBAAbBbBaBAbaBaBABaABAbAAAbAbbBBAbaaAAAaAababABaBBabAbbAaBbBAbAAaaabBBaBAbBbAabBbaaBAbbbaaAAbBbAABaBAabbakBBAaBaBbAabaBaBBaAbAbABaBbAbaBaaaaAbAAAaaabAabBbBbBAAaBBBbAAAbAaaaBabazBBbaAbAaBABbaBabBABbBABaBabbbBBABABaBaAPabBbBGBBbBBaAaBaaAAabBAABBaAaAbbbaaBbAaBBAbBAAbBaAbBABaaBBbaBBbBabaaaAAAWbBAaabbaBBABABbbaAaaBBABbBaaaABKaaabBaaBBbBbAABAAaaBAaBBAabbAabABAAabAabAbtAabBaAAaAAAaBbaABAAaBbbAbAaBaaBABAAaABaabBaBbbaABBBBBaABbAaAabbabBBBaBAaAaaBaABABbBAbAraBbbBBbuAbbabaaBAaABabBBBABAAaABbaBbbaBABbBbaAAbABaabBabaBbbBbAaBbaAaabAbBbabbabbbABBBbbBaBABBaBbAbabaabBaABaAAAababBABABbAAABABabABBAAAbBBAaBbaabABBBAbbBBbBAaBAbaBABAaAaBAAAABaAbbAbABAaaABAAbabbBBABBBabAabBaaAAbbaBabAbaaaBBAbAabbbAfbABAAbABbBBBababbbAbbBAAbbBAbBBbbaabaaAAABbbbAaabBBBBbabbBAaAbaABbaBaBaBBaaBbjAbaAbaABAbAabbBBBbAAABbAAbBbaabaAABBbABbAbBbABbaaabbbabBbAabAaABaaAaBaBAaaaBbaaAAaABAAbBaBaaBBbBbAABBbbabAAbbBbBBAaAbBAAAAbaBaAbAbbBbBbbbAbaBaaaAaaBaBaAbbbbBaBBaABBbABABAaAbAABAaAbAaaAAaAaABBbBabAaAAbABabAaAbbbAaBbBabaaBabBBBaAaAbaaBaaaBABBBAbAAabbBabaBBBBbababbAbBbABaAaABaaBbBBBbaAbbbaaaaAAAaaaaBAAaaAbabBbBBbaBBbAbBAEaABBBAAABAabbaAaABbaBBabBbBBBAaAbabaBAaBAaBbBabAABBAbBbaaBBaaBAaaaaBbBAAaABbBBAaABAAbaaabbabAAABaAbAAbAbbbbaBbABbbaBbbaaAabBBbRBAbBAAbAbBaabaBaaabAbBaBBAAabaJbAbBAAaBBABbaaAbaBbbabaabBbbAAbbaAaAABBbBAabbBaBbabAbAAbbAAAAaaBbAaaABbBaaAabAAaAaAABbaBBABbbABAABAbakBAbBBbbbbABAAaBaABaBBBBbBabbAbBaBbaAabaAabABAaAabaBABABbaBABaabaABBAbBbbBbbABAbbabABbaabaBabbbaabABaBaabbABbBAAaAAaaABbObbAbabBababBABbBbABBaABAABAabaBbBBaaABBBBaABBAbabAAbAaabAAFbBFAAbBbaaAbaaAbabbbbaBBBAbBbabbAaaBBBAAaaBBbAbaaAbaBbBaaabAAAbaAABaaBbABAbbaBbbBAaBaBaAAaABbbbBbBBBAbABBBbABAaaAabBbaAbAABbabaBBbAbaBaABBAbbaBbBabAbbbbAaaBBBBbaBBBAabAaBBAbBaaaAbbbABBBBaAABBbbbbBAbBaAAabBbBAbBbbbBBAbBaBbAaBbAbaAAababbbBAbbAaBBAAAAaaBaBABbbbAababABaABAaBaaAabAaAaAABbaBbbaAAaBbBbaaabBBbAbABBABaBbBBBabaBBABABAaBBbBbbABabaAAABUAAAaAbBabaABbAbaAbBBaBAbABBBABAAaBaBBBaaBabaAbaBBAbbAYaAABaBaaabAAABbBbaAabbabbaABBaAaAABbBBAaabAAaaBaZBbaaBabbABBaaAABbaBBbbaaBbABBABAbbaABAbabAaBBbBAaBaaabBABbbBcbbaAABBAAAbaBbaAbBAbBbAbBAaBabaAAbAabAaBaAaBAbABABaBAAaAAbbbBaAABABAaaaaBaAAaAAAAAaBBbAbAaaABaBaAbbaABAbBAAbbbaBbabAAAABabbAaBaBbbbaAaAababaaBaAbbBbbbAaabBbBAAbaabbBbAAAbAAaAaaBAAaBbbAAabbaabAbBabbaBABAbbbabbBaABAaBAaBbbaABAaabBbABBAAbBBbabAaAbaBAbBbBabAABbBABAAbBBBYAbbBaABaabbbBbbBbAbbabBBaAABAABIBAbBbaBAaBbBaAbbABbabBbbAaAbbaabBAbBABBbMAbBAbaabABaaaaaaaBaAaAaaaAAAAAabbBaabaaabAbBabbbbBBBABbaBbBAaBbbBbAbBAaABBbbAabbbABbABAAAbAAbbAaBBBAaBBbBbAaBABBbbAbbaAaDABAAAAAaAAbabbAaBbAbaABBAbbbAABBbbABBBABBBBBaaAAabaAaBbBBABaBaabaBaBAABBbaAAAaBAaBbpBabBbaBBaBbAaaBbbbabAbabBBbaBaaABbAAAabBBAAbAbabbBBbABaaBaBAABbABAbBaabABaBbAabbbBabABABAaAabAaAbaBAaAaBabaBAaaBBbaAabBAAbaaABbBAAbAbBAAAABABBAaaaAAAaABbBbABbaBBBbbbBbaAAAbABabBAABAbbbAbbaABabBaABAbaaBBBBbjAABbbbbBaBBaBabbBbAaaABAaaAABbababAaaABBaAaBBbAbBbBBAabBABbaaAbBAaAaAABBAAbbbaaAAaAaAABaBBAAAabBBaBbABaBbaabbbBAbBBaBBaBaAABbbbbbABBaBABaAbbAababbdbBbaAAAaBbBAAABaBBaaababAAAAABbABaBaBbbBBaBaABBBbaAAaaAABbBabAbAaAaAbbAAbBbBBaaBAABBbBbAaBbABAbbaBbabbaAbBbaAbaaBAbbBBBBBBAbaaAAABAaABbaBBBBaAbABAbBBaAABBabaAbAaBbaBBABAAbdyaBaBBAbAbbaaaaaqAbbAabABBBbBBBaaaAAbBBaABbABbBAAABBbbabAABBaAAaBbDAAaabBabBaAbAaAaaAAAabAABAbBaBAAAbbaaABBbabBAbbbabaAAabBBABAbbBBAbaABbAabbABABABaAabBBaBbaBBBABBaaBbabaAAaaaBbbbAaAaAbBbbabbbBaBABbbaabaAaAabAAABaaaBaABbBaBBbbaBbaBBaabBAabAaaabbBaBBaAAbbBbbAbBaabBbAAAAbbabAAAbAbAbBaBAABABaBbabBbaABabaAAABaBaAbAaAabABAaBaBaAbbbAbbbbbAAbaaxaAbAAAAWaBbAaaaBAaaBbabbaAAQaAaAABaAAbBABAAbbAabAaAabAbBBaabbbAaaBBBbBaaBAbbBabaBBbbaaBBBaBAAAbabaaaBBbAbAABaaABBBAabaabbababaBAAAAaBabBaAaBBaaaBBbABbBbbAbaAaAbAaBABAbABABAbAaaAabABBaBabbbaBBbbbBaBAbABBbAaaBBaAabAAbAaaBABBbBAaBaAAaAbBbabBaAbBBabAABbbbBBbBAaBAbBaBAAAbaBbaBAABabBabAbABabaBAAababbBbbbabaaBBabABbbAAAAABaBBaabBBAABbabBaBAAAbbABaBbBAaAAAAAAAaBBAabBaBBbAAabbbbbbABAaabAbaabbAaBbaBAbBaBAaaAabbbbaAaBAaABBBabAABBBaaABSaAAaAAbaAbbbbbBbabAaaBBabbAaBbBBaaAAAaBBBaabbBAaaBBBBabBbBaaBbAAABbBaaAbbabaBBbAaBbabBbaBbBaaabaaBaAaAaBAabAabAaEaAAABaaBAbBBbaABbBbbaBAbbaBAaaAuBABAaAabBbaBBAbAbaBBabaAbbabBBABbABabbbBBabbBabBbAABbbBBaaAbabBBAbBBBabbbbBaaBABBAbaaaABBaabBaabAbABaBabAabAbbaaAabAaBAABAbaaaAaAAbAbAaAaAAabaBABBAABbAbBbBABAaABAaAaAaBaABbBABbAaBAbbBbbBaabbbBAbbAabAAAABABAbAbbaBBBAaBBAbAbaAbaBABAAbaBbaAABBXbBaAbBAaBBabBbAaAAaaABabAAABABaAabBbBbbaBBbbAAbAABbaBbbAabBaAABAbBBbAaBaBbaBbAababbAAaBBAAbabAaaAbAABbaBaabBaaAbbbbaAbAbAAtBaaAabBBbBaBBbAaaABaBAbaBbbbaBAABaAbaBBaaAaabAabAaaBBbAbAABBbAaabAabAaabBbBbBaaaaababAbBBAAbbabaBbaaABbbBAbaAaBbBaBAabBABAAbBaBBaaaAbABbaAabBbaBbaBAaBABbbBBbABAaaAbAAbAaAababbAaBAAbABbbBabAaaAAAbAabAaBBaaaAaAAABbabAAAbBBBaBaBAaaBbBBaBBbbABbbaBaBBbAbAajaAAbabaaBAbaBaBaababBbAbAabAAABAaAabbAAAbbBBBaBbBBAAaaABabaaBAbBAAbBBbABAbaabaUabBAaAAaaBabBAbAbababbBAAAbABaAAAABBbBaAAAAaABBbABbABaBBaaBBAbABaaAaaBBABABBBJBbBbbbaBAAbbbbAAabaaaBaAbaAaAbAbabbAabbAbbaBaBbAaBaabBabBBBbabAaBaaBaAAAbBAAaaBAbBaBBbbaAaAxaAAabaAAbbBbBBabAbbabBaBAabAAbBAaAAbBAaBAAABAAAaaAbBbbAbAaAabBBBABaAaAabbaAaabAbAbaBBabAbabBAbABAbbaBaaAbaBabbbbaBAaBAaAbbAAAYabaAaBBAAAbAbbabAbaABbAABaABAabAAaBBabBBBbbaBbBBAaAabaaBbAAbaBABbaBbBbAABBBAAAAbdBBabbaaBBbBaBabBAabaAabBabBBBbaBBABbBBAABABAAAAABBABaAbAbAAaBBaBaBAAAAbbBbbaABAabaAyabAAababABbBabBaAabbBBbBAaBaaAABaBaaaaAbabAAaBbABAAbbaaBAAABaBBBaaaBbqbABAbBBBBbbaBBBbABAABBABAaBAbBbbAaAbbaaaaaaAAaBABbAabaBbabbbbzaAabABbabbAabBABbabABAabbAaaABABaaABaABbBBaBbbBBbBBbAbbABbBaaBbAbBAaBaabbAaBBAabbbAbBAaaaABAbBBaabAbBAaAabBBBbBnBBaOAaabAabBabbAbBAaVBaAaaAAbbaaABbAAbBAabBAAABBBbAaBaBAAAAbAAAABBBbaaAbbBAbAaBbAaaAabBBBaBBbBaBBAAbAAaaaaabbaaABBBBaBBBaBbaAbAAbBaBaABabBAaAbbAaabBbDAAaBbaaABAbbbBbBBBbBaaBBabaAaaAAAABbbBAaaaBAbaAAbAabbAbaaBAAbBBbabAabBaaaABaaaAABaabBAababAaAABbBbbBBAAbbBBBAbABaaaAABBAbAbbaBBBAbbabBaABBbBAaBbaAABaABabbABABbAABBbaABaAbbAAAABBbBaABBAaAaabAbBAbbbaAABbaBaabbaBaBbBbBbAbBaabbbAabbaABBAababBBaAaBbaBbBbjBbbbAaAAbbaAAAbAbAaBAABAbabBABbBbaaBABbBABAABbAbBBaBaBAaaaBAAABABBBAAAAAAaABbbbbBaBbabBBBaBaaAbBBBAHbaBAAabaaBABaaAaBaAABAbaaaabAaabBbbabaabBABBbBBabBbAaAabaaAAbAaBbbaBBbbABbBBAbAABABABBbbBabBaBabBBBAaBABaaABAbAaBBBBbBbAaABAbbAbabbbbaBAAbbAaAbabBBAABAbBbBaBbABbbbaAAaaAaaBBAbabaBabAAAaaAabBaABAAaaBABABaaBbAaBbabbAaaabAbbaaABbAbbaBaAAbBABAabAAaAbbaAbABbabbbabbbBBaBBBBaAaBAaAbbBBBaABBBbbAababbAAbAAAaBbaabAaABBbABAABaABaAbBbbbbaAABABBabbAABAbbbBbbBbbAaBBaaABaBbBBbaBAaAabbbBaABbaBAABaBBBaABaABAAAAAbaAbAbBabbAAAABbbaAABBabBAaBBBbbbAaAbBbABBNAABBaabaBaaAbBBbAABAaaABaABBAaaaABABBBAABaaaBaAbBBaBabaaAaaAaAbAABbBbABaAbBababAAbBAaaaAaaABabAbabbabBBabbBbBABBBBbbabABAAAbBbaBbaAAABbAaababBYaBABABaAabAaAAbABaaAAbabAbaAaAbAAbAaAAbBBbbAbbBabAABBaabBbAaBAABaBaABAaabbabAAAAaabaaBbAABBabAbAbaBBBaAAAbbAAAbaBAAbBBAbBbAbaaaaBbBaAbaAbBbbaABaabAAbbbBbbaaaBabaABbaBAaBAaBAbBBBbBaAabAbaABbaBBaAbABbBbbBabAbbBbBabbAabBaaBbbBbBbABababAaABAaaBaABbbBaAAbABBaAaBAbAbBBaBAaaabAbabaaBaaBABBaaabbAbBABbbBbbBAbABBaAabbAAAaABbaBAbaaAbAAaAbbBabJBBbAbaAbABbTAAAaAbaBaBBbBbaaABAbBbBaBababBbKBaABBBAbaBBabbaAAbbbBAbBBbbbYbbabaBaBaABBaBbBAAAbbaBbBbabbAaBBAAAbBAbbaAbAaBBAbAaBABbbBAbBAbBBabbaAABbABFaAbBBBAaAbBabbAaBBAAbaAbrABBaaBabbBaBABAbBabBaBaaaaaBAbBAAABbbabbbbaAabaabBaaBaaBaABbAABAbbBbBABAaabbABaBAAaaAaAAAabbaBbbBbaABbobBbBAABbbBabBBBAbbaBBAbaBAbbbBbBaaBbababBaABbbaabbBbAAbBBabABaabAAAbabAbbAbAaAAbBBaABBBbaBaAAAbBAaBbAaABBbabbAbaAbbbBBbAaabaAAAaaBabAaBaabAaAaBBabBBaAaBAbaBabbBaaAbabbAAbABaBABBBaAaAAAabBABbbABaBbBABAaAaZABAbAaaAbbBAaABBabAAbaaABBBbbbBaAbbBbAAABaBbAbBaAaAabbAAAAbbbaaabAbBbbbaAbBBbbAaAbBabBbBAAaABaAABbVABaBABbAbABbbBbABBaabBBBaababiAaaAAABbbBBbbABaaBbbaaAAbbBAABBAaBaPBaBbBBBBBbBBawbbbbbaabaaBabAAabbaaBaABAbAaaBabaoaAaABBBAaAbBABbBbAabbbBaabaAAAbAAaaaAaBBaaAaAaBBbbbAABbBaBbaBbbBBBaaBaabAaaaBAbBAfAaBaAbaaIAAABsBbAAabbiaBAbAaAbAABaBaaabAAAAAbAAaaGBbabbaBBABBaabbbAaaaBBbBBaAbBBABbAAAaBabAABbAaabbaabAaABABBBABBBBAAbAbBBAbbBbaABbbBBaaBBBABbBbaBABBbaaBbbAAAabBBAAbBaaabAbbbbBbbBAabbAaBAabbAABaAbAaBAbAbbAAABbaAAAabbBAAbbaBBabbbBAABBbaabAbbABBAABBAAaAAAbbBABabbaBAbbBABbbaaAbBAbaAbBBAaabBBAabbbaAABaAbBABBaAabBBaBaaAbaBBAaAabbAaaBaBBBBaaAaBBaabBBBbBBaBbBaAbBbaBBaaBAbaAbBbAAbBbaBBbAAABAAAbaabBBBbaBbbAabAAAbAaAbBaABBAbaAbBbaBABBBbBbbbAbAbabAbbaaABAaBBaabABbAbABaBAbAbBAAbaBbabBBaABbaaAAbBbBBBbBbABaABbbAblBAbBabBbaaAAbbBaAABAbBbaAbabdaabBBbAaBAaAaAbBabBBBAabBABAAAaBbBAaaAAaBaABaaAAABaAAAbBbBbaBaBaaaaBbaAABABaaaBbaAbbaaAaBAbaABaAbbbbBbbBbBaAaabAaBbaaabbbBBBABBbbabBabBBbaAbAaabbAbbAaBAABaBaAbbbaaabBAabaAbaAaaBbaAbBABAbBbBBAbaAbaAABABBbbBbbabBBaBbAABBABbBaAbabbbABbaaAAbBaBBaBbBBBAAbbaaAbbaAabBbAbabaaAaBAaABbBBABBAbBAaaaNBaaBBabaAABBababaaABAgABbBbaAAAbbAAAbaBBABBaBaababAABbBAbaaaabAAAaBaPZBABbBaaABaAbABBBbABbAaBaAaBBaABaaBaBbbBBABAbBaaaBAbAbVABbBAaBBAAaBBBaAbbaaaabbABAabAbaAAaBaabAAbAaBBAAaaAaaAaaBAbAAbbBaBaBBBabaBbabbAaAAbAbbAaBaABbBbaBaBBABaAaaAbaBbbaBaAaSbAAABaBaBbabaBBbAabbaAaAaabbBaBbBabbAaAAAAabABaaBbAABaaBBBABbaBbbBbABbBbBABBbABaaAbAbAbBAAaBBbbaBaaBbbbbAABbBBAbBbBBBbABBbABBAaBBaABABBbAfAaBBbaBBbAbbBaaaBABaABaabbAABYAaaABBAbAAabBbaAbaabbbbABaAaBBBbbBBaAbbaBBbBBbBAalABAbaaAaBaaABaBaBAbbAABAABABBbBbbBabbbbaBbAabBABaaBbBbaBaAbBBaAaBBbbbbaaBBBaBbBAbBBbAbABBBAMaBABAAbAaBBBAAAaBbBBBbAaBbbBBAabAbAABbBBaBAbbabaABABBAbBaAbaBbABmbAbbAaABaBBbAAbBBPBAaAABABbaBBBBbBaAaAABAAAABbABAbbAbAAabaaAABbBaBAbaaBBAABabbbBbBBbBAABbBbAbABAbBbBAbBbbBBaaAAAaaabAbAAAaababaAbBAAaAabaAbabBbBbAbBaBBabBAAABBBAbBabaABBBbbAaAbbAAaABaABBBbBaAabBbABBBbaBBAbAbbaAabAbaBbABbababaBaBbbBaAbabBbAaBbBBaBabBaAaabAbBAbAbAAabBaaAaABbaaaBBBbAABBbbbAAAbbBabAbbbBAbBBAabbBBaBAAbbbBAABAAbAaBBBABaBBBABaaABAaaBBAaBBAaBBBAaBBaAbBBaBabbAaAAabABBBbaaaaAAAAaBBBbbAbaABbBaBABBBAaABABBAAABBabBBAaBBAaaaAAAAABBBabbbAaABAABBAaBBbtabBBBBbaBAAAAAABAaAaAbaAaaaBBaaBBaABBAAbbbAAabaaaaAaAaabbBbbAbABBabAABABAbbBBBbbBbAAbBbaBBaBbABbaaAaBabbBBAAAAbbbaBBabBbBbaAaBaBBaABbBbalBbBbBABaBbBAAaBbAbABBbAABaABBBaBaBBAbBBbbBbbbbBBabbAbBbBABabBaBaAbBabaaBbAbAbbBAABBbaabaBbaAbbABABbbaBbBabbbaaaBBABAABABAabBBABbbaaabBBbABAabAAabbAbbBBBAababAAabAbAAabBAbbAaAbBbAaaAaAbbaaaBaabBAbBBAaBBbBBbbAABBaaaABaBBAAbbbBBbAabABbAaBbAaaAbAbBBAaaBAaBABBXaAaBBBaaabBBbBbAabaBbaabABbaABBbabAaAbbBabaABabbaabAbBaABBbABbBBbBAABbAbbaBaBAbaaBaBBAABBaALaaaBAAAbbbBbabbbAbaAabAbbaaAbaAaABbBBaaAAaAabAABAaABBAaABbaAABBbbAbababbABAbaBBaBbabBbAaaabAbBAAAaaBBAAabbbaBbbAbBBAAabaAabBBAABaABAAbbABAabAAbbAbbaaAbAbAaaAaBbABAbbbbaAAbABaAbaBBaBAaBBAAabAaAbAaABBbbBBBabBBaaAABbaBBBBbABAaaBBBabbaaabBbAaaaaABBbaAAAABAaaabbBababAAaBabAAaaBABaAbABaBbAaabbAAaaBaAabbBBBABbbABabBBBaAAbBAbBAZbBbaAAbaAAAbaaabaabBaAabBaaABaAabBBAbAAaBabBbAaAaAAbABbabbBAAxbBAbABBbABbAAABBBAaaabBBBBbbBaaAAbBABaBABabbabBbabAabAbabbBABBAbaBaAabABBaBBBbaaBbbBaBbBbABaBaBbBbAaBaaABbbbaBaBaBBbBBaaAbAAbaBBBAbaabbAACbaAbAbAbBBaAbAabAabaAaABAAAaBBBBbaabBbbbAabBaBaaaAbaABbBaabBbbbbaaaaaaAAaaaABaabBbBBBAAAbAABabbBbAbbbaaaBaabAAbBBABAaaBBbbBabaAaabbbABbBAaaBaAABBaaBbAbBBaABbbbBAbaAAAbaaAbAbbBbBbbbaAAAbAbAaAbBABbaBabAABBAaBaaaabbaAabBBaBBBabBaAaaBaBAbAbbabAbAabBaBBAbAAAAaabbbAbaAabaBBbAAaBAaaAAAbbAabBbaaBBABbapBbbbbbBABaaJbaabaBabBAaBBAabaBaaAAbabBbAbaaaAaAbBAAaaaAbAaAaAbaBBABaAaAABAabBabBbAAabBbbbaBaAAABaAbabaAABabaBbaBAaabaabaaAbBaAbBbaBABaABbbbAbAABBAaBaaAbAbAbaBbaaBbAaBBABaaBaaAAbBaBaAABAabBBaabAbAAbaaAABbaBaAbaAaABBABbbabbBBbBbabaBAabABbBBBabABaAABabBBbBBbbAbbbBBAAbbbbaaBbBaAAbAAbBBaBBbabbAabbbabbBABbaaAAabAABAabOBAABaBaBaAaabbBbbBBBBBBaBaaaBbBAAABaaAAAAAbBAbAbAaBAaAabAabBbBaaBaAabaBBAABbBbaaBBaAABaBABAAABBbbBbaaaabAabAbABBbAaBBaAAaAAbaaaAbAAabaBbabBAAABababAaBBabAababAaBbAAAbBaabbAAABaBabAbbbBBBBBabBabAaBabbbbaAaabbbbBbbbBAbabbbbbAAaBBAbaabAaabaaAaaABbaaABabBabBBAABAaAaBaababBBAAaBaBaaBaaBbaAAaBBbbBbbbBbabABAabAbBAABabAAABABaAaBabAaAAaaAbBababbababAAbbBABabbBbaBbbaaAaBaAAbabAaAaBbaBBaBbBBbbBbbBbbBBaBbBBAaaabABaAAAbBbABAAbbAbbAbAABBABLAabBbbAAabAbABBABBAbAbaBaAbABAbBaAaAazABbBaBbabABBaBbaArAAbBbabBBAbAbbAbBBbBaaabBBbBabBbAbAaBaBaABAAAAABbaBABaAAbaBbbBbabBAaaAbAabaBabAbAAAaABAABBaBbfAAAbbABABBaAbaaabAAbbbAbAAbabPaABBaBaBBzBBaaaaBAbABABbbBaBAAabbabaBbaBBAbAAAAbbbAAaAbABBbABAaBAbbbBABBABbaaabaAbAAAbAAABbBabBBBbBbABBBBbbAeBbABaAabAaBaBaaAbaAaAbbbAaaAaBabAbAaabbBbBAboAaAbaBaBaaBaaBbaBABBBAbABaAbbbABbzaabBmABAaABBABbBaAbaBbBBBABabbBaaABbAbbbBbAbaAAaBabbBbbtbbbAAAabAabBaaAAAAbBAAABBaBabABaAbaBbbaaBBBBaAAaBAbAAbBabAAABbBAabBBaaaABABBaaAababBaABaAaBbbBbAABAtAaAbBabaAABABaABBAaaABbAababAABAbabAbBabAaaAaaaBaAAbabBaBAaaBbbaababbbBBBbbaAbbAbbBaAbaBebbaBAbaBBBBAABAAAAaaABAAbaAabAbaBabABabAbbabBaaBbBABAbBABaAAaBbAABBabBabABAaBAbBbAbaABBaBbaAAaAAaaAbAaaaBbbaBAAbAAbBBBjaABAAbaAbAbAabbBBaABBbBBbaaaaBaAbABBBAABbabaaBbBBbBAbbbbBbaaBBaaaaAbAbBBaAABaABAbAaaAAaAbbbAbaaBBBbAABBbBaaaBBbBBAAaBbaaBaaBaBaABaAbBbBAAbBbabAAAbaBaaabAaabBBAbABbaaBBBAaBBAaBABaaAbbBBBAaaaAbabaBAABabbbabABAbaaBbBbbaaBBbbaAaabAaVaAAbbbBaBbAAaaaBABBaabSAaBBbbBAbBaEaAbBBaBAaAAAABbBABabbaaAABabaBaaBBbABaBaaBbbbbBbBbaababAaBbbAaaAbABaAbaaaaAAaBBaaaaBABbabaAbabBAaabbaBaBABaAbaBBaBaAabBaBBAbaAAabAAbaaAAbAabbASbBBbaabbbbbAABbbAbbAaaAaBAaabAAbbabBBBbBBAabBAbbBBAaBaAbAbAbABAbbAaBABAABaBAaAabAbAaAaauBaAbAbAbaBbabbbBbBabaBAbaBAbAbbaBabbAAABBaABAabbbBbaABBbBAaABABbazbBbaBaBbbbbAAAaBbBABABababaBbABBBBaAAAaaAbaBaabAABBBbAAAAAbABbbAbaaABbABBaBBAABBAaABaBaAbbabbABAabABaBaAbBaaaAaAbAABAaBABABAAABbABBbMaAbaaBlBBbbbBAAbbabaABagabbabABBABabbAbbbbABbbbBaAabBbAAABbAbbbbAbbbAbbBAbBbbBaABbBAABbBbAAbAabBBaAAAbBbbAbaABAAaAbAaAbABAAabaBBabaaABAAbaAAaaBBAAaaaabBAABBBBaBAABBaBAABbabBBAabbAaAAbBBBbAbAbAbbABBAAABaBaAAaAbabbbBABAbTAbaBbsAaAabababAbBABBabAAaBAaAbABbaBbAbaAaBAbababaBbAAAABaaaaaaaAbBabaAbAaaabABAaBaBAAaabABABBbbbBaobBaAbabAaBAaaaBaabbBABBBAaaBAAAaBaaAABAabbbbababaaBBaBabBbBBABAABbAABAbAabAaaAbBbbbbabaAbabBBbaAAbABababBbBAbbaAaBAbaaABAAbBBbBAAbaBbBBabBBBBbaBBaAAAabABaaaBBbAbabBABBabBbBBBBbbbAaBaBbaaAAAbaAAaBBbBabbBaaBAbABAAbAAbBbbAaAaAbsAbABaABaBBbABbaaBABAaBBabaAAAABbaBBaAABbaBabaBaAaAAAaaaaabaaABAAaBbBAbbBAAabBbaabAaabBBAbaaaabBBbbaBBABaBBbAAaBbbaABAbabAAaBbBAaABbbBaBAbAbaAAabAABaAABBaBabABBbaABbAABABAaBAAABabaAaaBBTAaAAABAbbbaAAaABABaBaBAAABBbBBBBBabAAbABaaaBBaaabAABbbBBBAbABabBABaBBAbaAAAaaJbaAbABbaAaAbaBAaAbbAAAbBaabbBABBaAaAaBBBbAAbaBBbbrBBAaAABABbbbbBbabaBaAbABbbAAbBAAbaBBBAAAAaaAAbBbBaBBABbabbbaABbaaAABABBBaaAABABBABbAbBBaaaBAAbBAAAAaBbbaAbabBaBBAbbaBBAbBbBbABbaaBAnAaaAAbABAaAabaABJaAaaAbBBBbabaBBBbBBaAaBBBBbbbaAbbaaababAbbABbBAaaAaAabaaBbBAbbbbAAAabaBBbABBbAbaAbABbtbbbabbbaAbbbaaaaAbBaaAaAaBAbBABbBBBAAabaaAbbBabaABbABaAbAaBbAbAbBAabAbbaBbbaaBaABAAaAbBAaaabAbaABABAbBBaabAbAAaBAbaAAbAbabaAaAaaAAAabBaaabaBBAababaBAbbbBaBbbbAABBBAabbbaBbabABABBABbAKabbAAaBBaABAaBBbAaabbBBBBBaaAABBBAbaGbAbbaBabABaaBBBbUaaaAAbBBABAAAbBaAAAaBbBBBBABBABAAAbAAABAaaBBbAcAbaBAabABBABbbaBAaABaAabbabAABbBbbbabBbBBBaabABabbAbBaAABBabaaBAbBaBaaBBbBBaBABbabbABbBBABaabAABbBbbABBBABABaabbbBBAABBbAaAaABabbAABAbAbbbBBABBAabBAaLABABaBaBbbaaAaAKABBAbBaABABBaaaaaAaBBaaaBAAbBAABBbaaBBAabABAbBaBbBAbAAaAaAaAbAbAAbBAAAABaaBaBbbbBbaaBbbbAbAbbBbBaAAbaaAaBaAbBAabbaBaabaAbabBAAaabhbbaABBABbaBabAbbaaBBAbbaAbAAabAABbBBAaABBBBAabBBBaBAAaaAAAbAEBabbAaBAAbBAAaBaAAbaAaBaaBaBbbbaAAbBaABBBabaABABbABABBBBaaaAabAAaBBbAaBAaBbAbbaAaabAAaabaAAaBBbbBAAbAbbaAAAAAABbbBabAaBBBbaaBABbaabbBBaAABAbbBaBaabAAbbaAaBABAABBAAABBBbbBbbbxbbABbABBaBabaababbBBBbBBbABBbabaaAbBaAaBBAaBaaBAaAabBaaAbABBbBAAaAaaaBaBAAababBAaabAaBBbbBaaAAABABaaAbbBBababAAbaaaBbAbBaaaAAAbbbbaaabAAaBAabbabBaaAAbAabAaBaaBBaBSaAaaaaaaaaaAbBBBaBaAbABbbBbbBabbAAaabaaAAbaaaaAAbAAABAabBaaAAbbbAAAbAaaAaAbBbBbbAbabbABbBaABbBAbBABBAAAaBBaBbAbbaBBaBAbAbaBABabbBaaabbBaAAaBbAAaabABaBaaAaAbABBabAabABbbaaAabABbbBbabAabAAabAaabbAAbaBaBBBaBBBAbBbbaBBabaaaBbAaAbbBBABbBbAaBaBBABAaaaBbaaBaBBBAaAaAbBABAababbaaAbBbbaabABBABAaNBAaaAAabaBaABabaBaaaBBBABbaBBAAABaAbaAAAbbAAAaAaaaBbAbBbbAbAAabbBBAbaBaABBbbAAAABbabBabaAbaaBAAaaAbAbbAaABbbbBBbBaabBaBbBabBABBbbBAbabBBAaBAbBAAaAABAAaABbbbBABAababAbabABaBaBBAbaAbBbAabBbabAAABABaaBBABbaAaBbBBbKABaAaaBAaAABAbabbaBAbABABbABabABAbbABabbababBBBbaABbABaAaabbbBAAAAaaABaabBAaabBAbaBaBbbBAAbBAbaABaBAbABbaBAABbaaaBABaBBbaBbBBaaAabaABbbBBAABAbbaabbBbaAbBAAbAbaAAabWABAaBAaBabbaAabaAaAaAbbbbAbBBBbvBbbabBaBaAbabBAaBbBAbbbaObaaBbabbabABAAAbAaaaabBabbbabaaBaAABabaaabBBBaaABAbbaBAaAbbAbBabbAbabAAaaBBAaAaaBabaaBbbBAAaAbbABbBBaABabaaAbAaAaBabAAAbAbBAbaABbBAaaABaaBBBBaaBbBABBbBbabABBbbbBaBBaBabaBABaBaBaBbaaAbbAbbBaAbAaBBababaAAAbBbBaaAAABbAbAuBBbaBabbAbAAaaAabaABbbBbbAaBAAAbaaAbbAaBaBBabBaAbbabABBaBbBBAabBIAAbAAaVbaAbAaAaaBaBAbaABaBBbbaABbaBBaBAbAaAABaBABAaBaABAbAAAabaBbBaBAbAabBBBaBABaaaaBaAbAaAbAbAaaABbabAABbbBbAbBBbBAabAAAbaBabaAaabbAAbbAaABAbbBBaAabAaaabbaABbFAABabaabBAbAABaBBBbaAbAbAabaaBbBBbaBAbBaabbAbBAAaBABbabaababBAaABAaBlaaAABaabbaabaBABbAAAbAaBBAAaAaAaBAAbBbabaBbbAbAAbaBbBAaaWaBaBbABHaBBAbBbBbaAAbBbBbAaAaaabbaaaABbAbabBbBbBBAAbABABAAbababaabbABaBaAbbabAabbABabbBBbbbBaAbaabaABAAAbaAbAAKbBAaBboBBAAAabAaBBbbaAbbbaaAAbaaaaBBBBBAAbaBaaaaABBabABBaAbBbabbaBABbBAAbBbbbBAabUAAbbAAbaBAbBBBbbBBBABABbbbBbbbLbAbbAbAbbBAaaaABbaaabABbabBBbBBAabbAABbBabAbbaabAbBABaAbAbaabBABaaBAbbAAaabbAbBBBaAABAabbbAAABaAbaAAAbaABIAbbbBAAbAAabABBBUAAAabbAAAbbbAbAbABBbAABbAABBAbBbbABbaBABaaBBaBAAAaaAaABBabbAaAbBbbabbAaAABAaaabbbBBbBbbBAaBBaBAbaaABABaBaBABABBABAABbbbaabABBaaBAAaAaABaAaAAbABABaBbAAbbaaabAaBbAaaBBabaAAbAabABBbBAbABaBBbabBbaaABaBaBBbbbbaBBAABaaBAabaabABBAAaAbaaAABBBAbaabBBbBabaABBABAabAbabABaBbbBBaAAaBAAaaAbbaaAaBaaBbAAAaaBbabAabAabAbabaBBBAbbaBabbbabAbAAAbaBAbAabaAaaBbaabaaBabBbbbBAABBbaaBbbBaBAaABABbbBbBbabbBBHaaaaaaaaBBbBAaabBAaAbAabAabBaABbAbAaBAbaaABBaBaaabbaBBabBBbAabbabbbaAAbaBAabaABAbbbAABBaAbabaAaAbaBaababbBBaaAababBaAaBabBAAaBaAbbAbAbAAaabBbABaAaAaaAbbAaAAabBabAAabbabaabbAbBAABbaBAbaaBBaAaBaaaBAAaaabbAbABBAABBBBAaaABBBaAbaBaaBaAABBAABBBAbBbbabbBBBbasBABBAbabABbABBaaBBBaaBBBBAbiAAABaabBBAAaBbbABBaBBbabbBaBaBBbbaBAaBaabAAaBbaAABABaBaAaaaAAAbBWaabAbbBbBAaBAAABABBaBaAbAabBabbaBbaaBBBbabbabbbYaBabBBBaABAbAABABbBBabAaBBAbBbBAaBBAAbbaAabBbaaAAabaaBAaAabbbABBAbabABAAaNbaaAaAbAbaBBabBBBBBbaaAbbAbaABABabaaAaBAabABaAbabaBBAaAbBbbbBBabbaABbabbbaBaBaaBAbaaAabaaABAabbbaBaBABBBaBBBBBAaBAbbabbBABbbaAAabAAtbbaaAaABaBaAAbAbBBAbBaBaAbbBBBabbbAabAAbAbBBaBbBbaAbaabbbBABABBAAABaBbABBabABAAABbaBBAAbbBBbaBAAAAbAAbbBBBbBbaabbBbAabaABbBBbaaAAaaBBabaBBbBaabaBbbbbaBAbBBABbbbAaaaaBBBAbaAaBBaBABbBbaBaBabAbbaAaaAbAabbaBAaBBbBABABabaabbAaBabBabbAbaaAbbAaBabAaAbBBBBaABaaBaaAaABBBAaBaAbBAAAaababIAaaabaaaabbBBaabAAbABbbbaaABABaaabBbBBaBaaBBAbBAAAAAbBaBbBaAaAaBBbBBAAaBbaBABBbbbAaaBBaAbAAaBAAAAbAaabbaAbaabBbbbBBaRABbbaaBAbAaBaaAaAbAaAbbABbbbbBABBAbbaaabbbaaABABAAbABbbAaaabBBbbBBbaAaababbaAabBAabaBbAAAAbbBABbabaaaBAbabbbaBaaAbAbiaaaBbbAbAaAAabbbbBbabAabaBbbaAbbbaaabbAbaBBaBabaBBbBbaABBbbabaaBbaBaabaBAbBABbabAAAABbaBbbbabaABBaAaBBaAaBaaaAbBBBAaaBBAaAabAaBBbaAbaAaAaaBAaaBBbBAbbbbaBbBbABAbAAbbbaSbaaBaAaaABBaaaABBBaBBABBaAbbaaBbBabbaBAaBaaabBbAbbAbAAAAAAAABAaaBBbABabAabaaAaaaBoaAaLaaBaBBaaaABbBAKAbbAABaBABAbaBaaAbbAaAabABAAbBbaBbabbAaAabaBbAaBAABbBABaabABbAaAaAaAAAbAaAbbBbbbAaAbBAabaBbaABBABabAbBBBbBAbAbBAaAaaabABbaBabaAaBbBabBBbBaBAbBBAaBbAAaAABabbaBbaAAabBaaaaaBaaBaAABAaBbaBbAaAbaBAaBAbBBBXBbAAaaaAbAaABBABAabbaBbAbbABaaAAAAaAbBaAaBbabBBABaAbBABBbBbBABAAAAbBaabAaaAAbAaaAbAaAaAABBbbAAaAbbBBbCabBabaAVbABBBaBbabBbaAaBBBAaAAaaAbaBAbGaBABbAbbBBabABbBBAaBBBAbbaABabBaaabaaaAbaaBbbAAbAAAaAbabaaABbaBbBAaaabbaAbabBaAAbAgBBBAaAaAbBBBaAAabABaaBbAaBbbbaBbbbBBbBBBABBaaBAABBbbABAaBbAABAbABabbaAAbbABAbBaBAAbaAAABBbTAABbAAAaABBAAAaABbABaAaaaBAABaABAbBaaaaabBabAAbabBaBAaABbAAbaaabBAaaabBBBBBaaAaAbbAaaABAABBbbaaaaBbaBAAaaaAaAaABbBbAaBBBBbbaaabbBBabBbBABbAaBBbaaaBAAabaAaBabBaAAaBaabBAaaBaBbbNbbbBbbBabAaAabBBAAABaBbBBBaabbAAAaBaBAaabBAAbabbAAbaaAbABABaBaBBABAbBbBaAbbbAbBbAaBaBBaaaBBbaAAabABbaBAabBbbaaabaaAabAbBAbAAAAAAbAbAaAbbAaBaBbbbBAbBAAaAaabAaABaBbAAaabaaAaAabABaAabbBBABaBbAaBBBAaAbAAbabAAAaaBBABBBAaAbaaaAaAbbbBbaBBbABBaBaAABbABaAaaABbAaBaBbbaBBBAaaBAaABAABbBBBBbABaBbABababBBAabBbbBBbbaBBAAbbaAaBBAaAbbAaaABbABaABBBBaBBABAbaABBaAbbBabbgBbBAABAAAaBbbAAaAAaaBaBbgAaAaaAAbAbBAaABaaaBaBbBbaAAbbAaeABbaaBABBBbBabABbAbababaaaabbAbABabAaBaaBBaBaAaaAAABABaAabABBBbABabbBBAbaabbbAAbbBbaAbBBbaaaAbaABbBBabbbaAAaBBbAbbbbAAaaABAmbaaABBaaBBaaBabBBAAbAbAabbAaBAABAbBbAaAaaBABaaaABaSbaBbababaBaaAbbbaabBBbaaAbbaAAAabbbaBBBAAABbaaAbBAbbGbBBAaAabAaabAaaaAaaBbbBaAbBabBbbBbaAAbAbABbbbAaAAAbBBbabBaabBbABaAAabBabaabAUBbbbBBAAaaBAAbbAaBaaABabAAAAAaBbaRbBbAbABbAAAbBabBaABHAAbAAABabbabAaaABABaBbbaABBAabAbabBBbbabAaBabbBbabBbBaaBBbBabAaAbAbbabBBbBaAAabBAAaBAbAAaaBaAAAbaAbAAABBAABAbbBABBBAbabaAAbAaBAABBbAaAabbBaAbABAbBbAbaabBabAAbaAAaAAAaBAabAAaAbBAbabAbaBBbBAbBAbbaAbAbabaabbbabBBaABbaBabBaABbABBABABaAaAbBAaBAbAbbBBbabBbBabBBabbBBaBbAABbAaABAabbABBaabAbAbAAbbABAbBbaabbAbBAaBAABabbbbABaOaBbaBaABbbaaBABBBaABaAAaAaAAAbAbBAAABAbABBBAbababABbabAaaABAaBBAABAAaaAAaBBBbbaAbbabAAbBAAAbBBBBaabbAaaaaBbbaaAbBbABbaBAabBaBAAaAAABBaBbBAaAaaBBbbBbAaAabbaaABBBBBBaBABAbbaBBABbAAAbaaabAAbaaAAaAaBbbABaAaAbbaaAaBAaAbAAbaaAaBABBaBbaBaBbAAAaaABbaAAabAabbaaAabAaaAbaBbBAAaaAbbaaABAbbaaAAABaaABAAbABBabbaBBaBbAaBBabbbBAbAbabABBAbBBabaAbbabbABbaAaAaBBbBbbAbaBaAAbabABbabBabBaaABBBABABBBAaABabbBbBaAYafBbAbABBabaBABBbbaAAaAbBbabbaABabbAABBaBbABabAaaAAbaBbBbaAbAbBbbabAbbAbAabBbabbbbaABABBbaBABAabbaAAAbAabBabAaBbabBBbaAbBbbbBbAbaabaaAbbabbaBAaaAbbBAbaBAbbAaabgBaAbABbaaABAabaABaaabbaAABbabBBbbBbabaAABbAbBBAaabababbBAAAabbaaABbbabAbabbabaBBbbbAbaaaAbbABAaAaBABBBBaAAbbbbABAabABAbAbAaaaabABAbBaBBBbbBaBBAaABABbabBaACBbAaBbbbbBbbAaBBaBbbABbAaaAababaBaaAABaBAbBBabAbBBbBAbBABabAAABaAbaBaBAmAaAaabAAbAbbABbbbbBAABBbaaABbaAABBbBBBaaaaABbBaBABaABbbbaaAaBbaHAbbaaanbaaBBBbBabBbabaBBABBAbbaAbbbAAabABBBaBbAbaBabBAaaABBaAbaBbbAaBbABABBbbbbbBABaBAAaABaABbAbAaAaAAaABbabaABAaBbBBbbBbAaaBbBBaBbaBBBAAaAaAaaaaBAbbabBBAbaABabbabaBBaaABBbAaaaabaAbbababaabBabBBbBBababaBBBBABaAAAABbBaBBBbaaaABBbABbBbAbbABbababbBaAAAaBBbaBabAaAbbababABBBbbAaaBBbbbbABaaabbAabbaabBaaaaBbAABbaAbaBAbbaaAAaAaABBbBaBBbBABAbaAAAabBbbBAAAbaaAaABbbbBbABBaBaAbAaAAaABBbBaABbaaAAaaaABabaAaAABAaBBAaBBBbAABaAaBaBbBABABBBbBaAaBaAaaBaBaBAAabABbbbbbBAaAabAbAAbbAabbaABABaABAAABbbAbabaaBaabBABAaABBaaAAalbbbbAaBaABbBBBbbaAbbABbAAAabGBbbaBBbabbAaBabBbaBbaAbABaaaAbBBBbBBAaABAAaBAAbbaAAbBAAAAABbAAABBbAaBbbAAabAAbbBabAaaBAbaaBAaBbAbbAbBBaBbAbBBbBBaAAaAaBBAabbAbAbaAaAaBbBaabaBBBAbBAbbAAAbbBaBbbabAbaabABAAAbBbbaBbaaaabAaaABAAabbbBBaBbbabBAaBabAaAbBbBaaABbBbaAbabAbBaAaBabaBabaaBaaaAaaaabbbbaaBAabAabaaBBaBBbAAbbBAaBaABAbBBbBAaBaABbaaaBbaBBbBbaabBbaaAABAbbbbbAbbaBAaBAbaaBBABBaBAAAbBAbbBABbabBbABaBAAAbAbbbbaBbbABaababAAbaBAaABbAaAbbBAabaAAAaBAbAaAaaaBBbaaabAaBAaBbaaaaBbAABAbbababBBbAaABaABbaaBABbAbBaAABbBBABaAbBBqABAAbbbbBaBbBBabABAbaABAaBbabABBaaBbABBBBbaAaaBBBAAABaBAAabABBaaABABbAbbAabaaBAbaAaAABAbbabBbaABBAaaBBBBBAbAaBAAaaBbAAAbABBAbbAbbBbbBBBABaBAababABaAbbBBaBbbaaaaAabbBAABABaBbaabbaBaBBAAabBbAbbbaABABAaAaBBBbBbBABaaFBbAaBAAaAbabBBBAabaaAbbAbBAaAaABaAAaABaABaBbbBAaABAaaabAABBbAaBBABbaabaBAAAbBabBabAbBWbaBAaabbBAAAabaAAaBABbBbbbAAAaAababbbbBbbbubAAAbBaABBAAAabbAabBAbaaBABbbBAbBaBabBAAbLABbBAbaBbBaABbAAaBBBababbabbbaBbBBaAaBbbAbabbAabaAaaaBAaAAabbaaBAAaBaAbBBbbAaBBaAbbAAAaAAaaaAauBbaAabBbbbBbbbababAAaaBabBbBBABAaBbAABaABBAAaBaBAAaaAaaBBBbbABaBbbaBABBABaaBAbBaABbABABAabbaABbaABbABabAabABaBAbBbAaAAAabbABaBaAbbABBAabAbbbbbBbaaAbAaBbaBBBBBbbBaQBbAbBbbAaaBabbbbaaEaaaBBbBbbbAABAbbbABBBBbbaBaBBBAAAbABAbBAbaBbaBAAAbbBaABBBabABAaaBAAAaabbaAaABbBbBbaBaBABAaaBBbBbbBAAAbABAaAaabbABABBAABAabAAAABAbbAabbbBbabaabbabbAbbBAbbaAaBAbaBAAAaBAbaAbAbbiBbAbaABaBAbbbBbBaabbAABbabaaaABAbaaAaaAaBBbbAABaBbabAbAABBAABbAAbBBAbABaAaBabbAaaaBtABaBAbAbBAaBBaBbBBAaabbBATAbaBBbAbAbaBAaabbbAaBBabBAABBAAaBMaBbbabAaaBbbaBaaAaAaAaabBabBaaAbabYbBbXaBBbBbbDbbAbbaBBbbAaBBbBaBABBabaBaBABbBaaBabBbBbabbaaAAABaabBbAbAzaabBbBaaAbbBBBaAbbBABbAAABaBBaABaaaBaaAABABaAABAaaAbBAAABababAAABBbaABABAaABBBbabbYbaAaBbBbbaBbbABaabAabBbbBaBabBAaBAbaBaabBBBaBBaAAbaBABbbAbabaaaBBBbbaAabABabBBABBAbbabBbbanABBAabaAABbAAaaBbBaababBbABaBbAabAbBABBBAabBAaabAbabBabAbAbaABBAaAbbBbabbbBBbABABAbBbAabbBABaBAabBaBBBaaaaAABiBabAAAbabbAAbaBbABBAAaBbBbBaBAAbbaBAAaAAaBaAabABABaBbabABAbbbaABBaaabBbaabbBaAaaabBAbaaaaLbBAABAABaaAbbBaaAbaBaBBBAbbaBBbabAAABBbbAAAAaAABAAbabbbbAAbabaBaAABBaabBAaaBbBAbAaaabbaBABabABBBaAaBBbabbaAAabAbBbBaAaaaAbAbABBAbaBBBaAaAbbbaBBbbBBAbbaAaAaaAaAABaBAAbaABBaabbBaaaAaBBbIbbbbBabaAAbABaBbaBBBAbbAbabBAAAbBAaAbAAAabaaABAabAAAaWaAAaaBAaAaAABaBbbaAbbbBBaaAabBbaAABaAaBAAbBaaaBbBaaBabBbBbbBAbABAabAaAAabBBaabaBbaAabaaAbBABaBaBBnAaAaBbAbBabbbBBbaaaBbABAAAbAbAbbaABBAAbbbABAAbABbBAabBbabaaAbBAbbaaAaBabbbABBbBABaBbbAAaABBbBBbBabaBBABBbbbBaabaBaaaabBaaBAbaABBBAAaBbbAaABaBBBbBbaabBbbAbbAaAbbBabbBABaAABbBbAAAAaaAABABbBBAbABAABBbBaaBbBbAbAbaaAbBBBBaBAAabaABAbAaBAAaAaABABBaAbBBBBbbbBbbaabBBbbBAaaAabbbaAaAbBaaBBBabbAaBAbbbbAbAABABABBaBAbbbAAAAAbaAbBBAAbBbbBbaABBbAAbABaABBaaBABBaaBAaBaababABaaABAAgAaBAaAbAabABABVABabAaaBbBAAbabbbbbBAAbbbAaAAABAabbAaBAaAbaaBbaBbbbAbaaBAbaaBbBaBBABaabaBbABaAABBBaaaAbabBbBaBbaaAAAbAaAAAbaabbyBbbBbbaABaABBAbbabbaAAAaabaAAbAaAAaaBabbaBBbBBaAAbBbAbbAbAAaaaBbaABBAAaBbaaAbbAAabbaaaBBBbaaAbBbABABBAAaAaAABAbbBAaaBBAaBbbBBaaaAbaaBBAaAabABBbAabAbaAabBbbBaAABBbAabaaaBAbaaAbabaBabBaVABBAAaaAAaBBAAbaAaabAbbaAabbbAAbaABaABABaABAABBABBaAaAABabBbABqbBaBBbAABABbAABaaAaAaaAaaBaAAAabAabbaAaBBaABaBAzaBBbBAiAaBabaABAabaABaaBbbbaaBBAbbAAbBBAAAAAAaAbbabaBbBABABBAaaAABBBAaabbabbbbABaaabBaAaBABBbBbAAaBaAbBbBAaBBBAABbBAaaAABBbAAbbbBAaBbBBaBbBAABBbBAaAABBbbbBAABAawBAaBAbBBBBABBABbBaBBbaBbBBBABAbBbBABaAAbBAbbBaBbBbABaBbBAbAABababAabaaABAaaaabbaBbaaabaaeaBaaAaaaaaBaAbsAaBabbAaAabAAbABbaAABaabaAaBABAAbbBbaBAaAbbBABAAaBAaaaAAbBBABBbABBAbBaaaAABABAabbaBaBAbAaABaBBAABBAAbAbABBAAABBbbaaabBBAabBAaUaBbabABABabbaBbABaBBABAAbBAAaBbaAbABBaAaBBBbbAbbBbaAaAaBbBaaBBbAAabBaBABABaaAbbbVaABAbaBaBaaAbAbAbABbAAAbAbAAAbbBBBBbBBbBaaAkBaBAaaBbBabBAAbbabaAaaBaBaABAbbBAAbAAAAaAabBbaAbaaaAbaBBBbBbaBaBbabBAaaBaabAaAABbbBBBAbbbbABBbABABbBbaBBbABBaAbAbAAbAbAAbAabBABabBaaABaBoBBbAaBaBABABAAabBbAABAAabABaBABaBBbaABbBAaAaAbbbbABBBaBABAbbaAAbBbAbBBaaB";

        System.out.print((new Sort_Characters_By_Frequency()).frequencySort(s));
    }

}

347. Top K Frequent Elements

Given a non-empty array of integers, return the k most frequent elements.

For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].

Note: 
You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
package com.leetcode.array;

import java.util.*;

public class Top_K_Frequent_Elements {
    public List<Integer> topKFrequent(int[] nums, int k) {
        // 使用 map 统计 nums 中数字出现的频数
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        // 根据数字出现的频数,将 map 中的 key 丢进 桶中 bucket
        // bucket[] 的下标表示 key 出现的频数
        Set<Integer>[] bucket = new HashSet[nums.length + 1];
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            if (bucket[entry.getValue()] == null) {
                bucket[entry.getValue()] = new HashSet<>();
            }
            bucket[entry.getValue()].add(entry.getKey());
        }

        // 将 前 k 大的数组放入 result 中
        List<Integer> result = new ArrayList<>();
        int count = 0;
        for (int i = bucket.length - 1; i >= 0; i--) {
            if (bucket[i] != null) {
                for (Integer num: bucket[i]){
                    if (count >= k)
                        break;
                    result.add(num);
                    count++;
                }
            }
        }

        return result;
    }

    public static void main(String[] args) {
//        int[] arr = {1, 1, 1, 2, 2, 3, 1, 1, 1, 1, 1, 2, 2, 2, 2, 6, 5, 4, 43, 23, 2, 2, 1, 23, 2, 2, 1, 3, 2};
//        int[] arr ={1};   // 注意桶的大小
//        int k = 1;

        int[] arr = {4, 1, -1, 2, -1, 2, 3};
        int k = 2;
        // -1 2 1 3 4  输出错误!应该还是 -1,2

        List<Integer> result = (new Top_K_Frequent_Elements()).topKFrequent(arr, k);
        for (Integer num : result)
            System.out.print(num + " ");
    }
}

作者:HeatDeath 发表于2017/11/26 16:00:53 原文链接
阅读:16 评论:0 查看评论

[bzoj 1101--Poi2007]Zap

$
0
0

FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d。作为FGD的同学,FGD希望得到你的帮助。

莫比乌斯反演的处女题。其实还是较水的,首先先把a%d,b%d,这样问题便简化成求gcd(x,y)=1的对数了。f(i)表示的是gcd(x,y)=i的对数,F(i)表示的是gcd(x,y)%i=0的对数,那问题又简化成求f(1)。
熟悉莫比乌斯的同学明白在知道f与F的含义后,这题便可做了。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int pr=0,prime[51000];
bool v[51000];
long long Mu[51000],sM[51000];
void get_Mu()
{
    memset(v,true,sizeof(v));
    Mu[1]=sM[1]=1;
    for(int i=2;i<=50000;i++)
    {
        if(v[i]==true)
        {
            prime[++pr]=i;
            Mu[i]=-1;
        }
        for(int j=1;(j<=pr && i*prime[j]<=50000);j++)
        {
            v[i*prime[j]]=false;
            if(i%prime[j]==0)
            {
                Mu[i*prime[j]]=0;
                break;
            }
            Mu[i*prime[j]]=-Mu[i];
        }
        sM[i]=sM[i-1]+Mu[i];
    }
}
long long find(int x,int y)
{
    if(x>y)swap(x,y);
    int last=0;long long s=0;
    for(int i=1;i<=x;i=last+1)
    {
        last=min(x/(x/i),y/(y/i));
        s+=(sM[last]-sM[i-1])*(x/i)*(y/i);
    }
    return s;
}
int main()
{
    get_Mu();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int a,b,d;
        scanf("%d%d%d",&a,&b,&d);
        if(d==0)
        {
            printf("0\n");
            continue;
        }
        long long ans=0;
        ans=find(a/d,b/d);
        printf("%lld\n",ans);
    }
    return 0;
}
作者:lixuanjing2016 发表于2017/11/26 16:06:55 原文链接
阅读:23 评论:0 查看评论

Unity Shader 学习笔记(28) 噪声纹理、消融效果、水波效果、噪声雾效

$
0
0

Unity Shader 学习笔记(28) 噪声纹理、消融效果、水波效果、噪声雾效

参考书籍:《Unity Shader 入门精要》


噪声纹理

通过纹理深浅可以作为一些变换的阈值,或者透明度等。=


消融效果(Dissolve)

常用与角色死亡、地图烧毁时效果。

Burn Amount从0变化到1。

Properties {
    _BurnAmount ("Burn Amount", Range(0.0, 1.0)) = 0.0              // 消融程度 0为正常效果
    _LineWidth("Burn Line Width", Range(0.0, 0.2)) = 0.1            // 消融效果时的线宽
    _MainTex ("Base (RGB)", 2D) = "white" {}                        // 漫反射纹理
    _BumpMap ("Normal Map", 2D) = "bump" {}                         // 法线纹理
    _BurnFirstColor("Burn First Color", Color) = (1, 0, 0, 1)       // 火焰边缘颜色值
    _BurnSecondColor("Burn Second Color", Color) = (1, 0, 0, 1)
    _BurnMap("Burn Map", 2D) = "white"{}                            // 噪声纹理
}
SubShader {
    Tags { "RenderType"="Opaque" "Queue"="Geometry"}

    Pass {
        Tags { "LightMode"="ForwardBase" }

        Cull Off    // 关掉剔除,正反面都渲染

        ...

        fixed4 frag(v2f i) : SV_Target {
            ...

            fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;
            clip(burn.r - _BurnAmount);     // 如果小于0,该像素会被剔除

            //_LineWidth宽度范围模拟渐变。t为0是正常颜色,为1时位于消融的边界
            fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);
            fixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);  //两个烧焦颜色做插值
            burnColor = pow(burnColor, 5);  // 加强颜色模拟烧焦痕迹

            UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
            fixed3 finalColor = lerp(ambient + diffuse * atten, burnColor, t * step(0.0001, _BurnAmount));

            return fixed4(finalColor, 1);
        }
        ENDCG
    }

    // 阴影投射,直接剔除掉阈值内的像素即可
    Pass {
        Tags { "LightMode" = "ShadowCaster" }

        ...

        fixed4 frag(v2f i) : SV_Target {
            fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;

            clip(burn.r - _BurnAmount);     // 剔除掉透明的

            SHADOW_CASTER_FRAGMENT(i)
        }
        ENDCG
    }
}

水波效果

噪声作为高度图,修改水面法线。使用Schilick菲涅尔反射实现:fresnel = pow(1 - max(0, v·n),4 )

菲涅尔动态水面效果:

Properties {
    _Color ("Main Color", Color) = (0, 0.15, 0.115, 1)
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _WaveMap ("Wave Map", 2D) = "bump" {}                           // 噪声法线纹理
    _Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}           // 立方体纹理
    _WaveXSpeed ("Wave Horizontal Speed", Range(-0.1, 0.1)) = 0.01  // 法线平移速度
    _WaveYSpeed ("Wave Vertical Speed", Range(-0.1, 0.1)) = 0.01
    _Distortion ("Distortion", Range(0, 100)) = 10                  // 折射扭曲度
}
SubShader {
    // 所有不透明物体渲染完后
    Tags { "Queue"="Transparent" "RenderType"="Opaque" }

    // 抓取屏幕Pass 存入_RefractionTex 
    GrabPass { "_RefractionTex" }

    Pass {
        ...

        #pragma multi_compile_fwdbase

        ...
        sampler2D _RefractionTex;               // 对应GrabPass
        float4 _RefractionTex_TexelSize;
        ...

        v2f vert(a2v v) {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);

            o.scrPos = ComputeGrabScreenPos(o.pos);         // 抓取屏幕图像的采样坐标

            ...// 计算世界空间下切线法线等,构造转换矩阵

            return o;
        }

        fixed4 frag(v2f i) : SV_Target {
            float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
            fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
            float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);

            // 对法线两次采样(模拟两层交叉水面波动),相加得到切线空间下的法线方向。
            fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;
            fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;
            fixed3 bump = normalize(bump1 + bump2);

            // 计算偏移量,切线空间
            float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
            i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;            // offset * i.scrPos.z 模拟水越深,折射越大
            fixed3 refrCol = tex2D( _RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;

            // 计算法线到世界空间
            bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
            fixed4 texColor = tex2D(_MainTex, i.uv.xy + speed);
            fixed3 reflDir = reflect(-viewDir, bump);
            fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb * _Color.rgb;

            // Schilick菲涅尔近似等式
            fixed fresnel = pow(1 - saturate(dot(viewDir, bump)), 4);
            fixed3 finalColor = reflCol * fresnel + refrCol * (1 - fresnel);

            return fixed4(finalColor, 1);
        }

        ENDCG
    }
}

噪声雾效

前面实现过雾效在同一高度的浓度是一致的,这里使用噪声模拟雾的浓度,实现非均匀雾效。

在之前实现的雾效添加一些属性。

Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _FogDensity ("Fog Density", Float) = 1.0
    _FogColor ("Fog Color", Color) = (1, 1, 1, 1)
    _FogStart ("Fog Start", Float) = 0.0
    _FogEnd ("Fog End", Float) = 1.0
    _NoiseTex ("Noise Texture", 2D) = "white" {}        // 噪声纹理
    _FogXSpeed ("Fog Horizontal Speed", Float) = 0.1
    _FogYSpeed ("Fog Vertical Speed", Float) = 0.1
    _NoiseAmount ("Noise Amount", Float) = 1            // 噪声数量,0为不使用噪声
}
fixed4 frag(v2f i) : SV_Target {
    float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth));
    float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolatedRay.xyz;

    float2 speed = _Time.y * float2(_FogXSpeed, _FogYSpeed);
    float noise = (tex2D(_NoiseTex, i.uv + speed).r - 0.5) * _NoiseAmount;  // 随时间偏移雾效,-0.5是把范围控制在[-0.5,0.5]

    float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart); 
    fogDensity = saturate(fogDensity * _FogDensity * (1 + noise));  // (1 + noise):浓度倍数范围在[0.5, 1.5]内。

    fixed4 finalColor = tex2D(_MainTex, i.uv);
    finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);

    return finalColor;
}
作者:l773575310 发表于2017/11/26 16:30:44 原文链接
阅读:18 评论:0 查看评论

Kali Linux中下载工具Axel的安装和使用

$
0
0

前言:

Axel是一个多线程的HTTP/FTP下载工具,支持断点续传。

Axel的安装

apt-get install axel

Axel的卸载

apt remove axel

安装完成之后输入

axel

回车就会显示Axel的帮助页面,Axel 2.15-1版本的帮助页面原文如下:

root@kali:~# axel
Usage: axel [options] url1 [url2] [url...]

--max-speed=x       -s x    Specify maximum speed (bytes per second)
--num-connections=x -n x    Specify maximum number of connections
--max-redirect=x        Specify maximum number of redirections
--output=f      -o f    Specify local output file
--search[=n]        -S[n]   Search for mirrors and download from n servers
--ipv4          -4  Use the IPv4 protocol
--ipv6          -6  Use the IPv6 protocol
--header=x      -H x    Add HTTP header string
--user-agent=x      -U x    Set user agent
--no-proxy      -N  Just don't use any proxy server
--insecure      -k  Don't verify the SSL certificate
--no-clobber        -c  Skip download if file already exists
--quiet         -q  Leave stdout alone
--verbose       -v  More status information
--alternate     -a  Alternate progress indicator
--help          -h  This information
--timeout=x     -T x    Set I/O and connection timeout
--version       -V  Version information

Visit https://github.com/axel-download-accelerator/axel/issues to report bugs

Axel的用法如下:

命令格式:

axel [选项和参数] [下载链接1] [下载链接2] [下载链接3]

常用的选项及功能描述如下:

-a 显示进度条
-s [x] 指定每秒下载速度的最大比特数,“x”一般设置成200000以上(单位是“字节/秒”)
-n [x] 指定同时打开的线程数,“x”一般设置成10以上
-S [x] 搜索镜像并从X servers服务器下载
-o f 指定本地的输出文件(即指定本地的另存为目录)
-N 不使用代理服务器
-v 显示更多状态信息

注:
1.上述选项后面的“[x]”中的x代表数字,为该选项的参数。
2.如果不指定“本地保存目录”,则下载的文件会保存在执行下载命令时所在的目录(即当前目录)。
3.Axel支持断点续传,如果下载过程中断,可以再次执行原下载命令,即可从上次下载的进度处开始继续下载。
4.Axel可以从多个地址下载同一个文件。
end
更多内容请访问我的个人网站荒原之梦

作者:wy_bk 发表于2017/11/26 16:37:45 原文链接
阅读:19 评论:0 查看评论

Hadoop源码分析:HDFS读取文件

$
0
0

Hadoop源码分析:HDFS读取文件

上一篇博客http://blog.csdn.net/chengyuqiang/article/details/78636721分析了HDFS的DistributedFileSystem对象的创建过程。
然后就可以按照HDFS的API对HDFS中的文件和目录进行操作了,如列出某个目录中的文件和子目录、读取文件、写入文件等。

1.1 FileSystem.open()

与使用Java IO读取本地文件类似,读取HDFS文件其实就是创建一个文件输入流,在Hadoop中使用FileSystem.open()方法来创建输入流,open()方法是我们此次源码分析的入口。

    public static void readFile(String filePath) throws IOException{
        FileSystem fs = getFileSystem(filePath);
        InputStream in=null;
        try{
            in=fs.open(new Path(filePath));
            IOUtils.copyBytes(in, System.out,4096,false);
        }catch(Exception e){
            System.out.println(e.getMessage());
        }finally{
            IOUtils.closeStream(in);
        }
    }

1.2 进入open(Path f)方法

该方法返回的是一个FSDataInputStream对象。

  /**
   * Opens an FSDataInputStream at the indicated Path.
   * @param f the file to open
   */
  public FSDataInputStream open(Path f) throws IOException {
    return open(f, getConf().getInt("io.file.buffer.size", 4096));
  }

1.3 进入 open(Path f, int bufferSize)方法

发现这是个抽象方法

  /**
   * Opens an FSDataInputStream at the indicated Path.
   * @param f the file name to open
   * @param bufferSize the size of the buffer to be used.
   */
  public abstract FSDataInputStream open(Path f, int bufferSize)
    throws IOException;

下面进入DistributedFileSystem类的open(Path f, int bufferSize)方法

  @Override
  public FSDataInputStream open(Path f, final int bufferSize)
      throws IOException {
    //统计信息
    statistics.incrementReadOps(1);
    //相对路径转换为绝对路径
    Path absF = fixRelativePart(f);
    return new FileSystemLinkResolver<FSDataInputStream>() {
      @Override//核心方法
      public FSDataInputStream doCall(final Path p)
          throws IOException, UnresolvedLinkException {
        final DFSInputStream dfsis =
          dfs.open(getPathName(p), bufferSize, verifyChecksum);
        return dfs.createWrappedInputStream(dfsis);
      }
      @Override
      public FSDataInputStream next(final FileSystem fs, final Path p)
          throws IOException {
        return fs.open(p, bufferSize);
      }
    }.resolve(this, absF);
  }

在该方法中,statistics是一个org.apache.hadoop.fs.FileSystem.Statistics类型,它实现了文件系统读写过程中的一些统计,例如自从该HDFS对象建立以来,读了多少字节、写了多少字节等。在返回结果的时候,创建了一个FileSystemLinkResolver对象,并实现了此类的两个抽象方法, 最后调用了resolve()方法,其中doCall()方法和next()方法都在resolve()方法里用到了,只是next()方法只是在resolve()方法异常捕获时才调用。所以跟踪doCall()方法,doCall()方法里的open()方法有3个参数其中src表示要打开的文件路径,buffersize表示缓冲大小,verifyChecksum表示是否校验和。

1.4 进入dfs.open(String src, int buffersize, boolean verifyChecksum)方法

  /**
   * Create an input stream that obtains a nodelist from the
   * namenode, and then reads from all the right places.  Creates
   * inner subclass of InputStream that does the right out-of-band
   * work.
   */
  public DFSInputStream open(String src, int buffersize, boolean verifyChecksum)
      throws IOException, UnresolvedLinkException {
    checkOpen();
    //    Get block info from namenode
    TraceScope scope = getPathTraceScope("newDFSInputStream", src);
    try {
      return new DFSInputStream(this, src, verifyChecksum);
    } finally {
      scope.close();
    }
  }

checkOpen()方法表示检查文件系统是否已经打开,如果没有打开,则抛出异常–FileSystem closed。最后,在这个方法中调用了DFSClient.DFSInputStream()的构造方法,创建DFSInputStream输入流对象并返回(DFSInputStream是对客户端读取的输入流的抽象)。

1.5 进入该DFSInputStream构造方法

该方法先是做了一些准备工作,然后调用openInfo()方法,openInfo()方法是一个线程安全的方法,作用是从namenode获取要打开的文件的数据块信息。也就是说主要是为locatedBlocks对象赋值。

@InterfaceAudience.Private
public class DFSClient implements java.io.Closeable, RemotePeerFactory,
    DataEncryptionKeyFactory {
  ...

  DFSInputStream(DFSClient dfsClient, String src, boolean verifyChecksum
                 ) throws IOException, UnresolvedLinkException {
    this.dfsClient = dfsClient;
    this.verifyChecksum = verifyChecksum;
    this.src = src;
    synchronized (infoLock) {
      this.cachingStrategy = dfsClient.getDefaultReadCachingStrategy();
    }
    openInfo();
  }
  ...
}

1.6 进入openInfo()方法

该方法中如果读取数据块信息失败,则会再次读取3次,主要调用了方法fetchLocatedBlocksAndGetLastBlockLength()方法来读取数据块的信息。该方法名字虽然长,但是说的很明白,即读取数据块信息并且获得最后一个数据块的长度。为什么偏偏要获取最后一个数据块的长度呢?因为之前的数据块大小固定嘛,如果是默认的,那就是128M,而最后一块大小就不一定了,有必要获取下。

 /**
   * Grab the open-file info from namenode
   */
  void openInfo() throws IOException, UnresolvedLinkException {
    synchronized(infoLock) {
      lastBlockBeingWrittenLength = fetchLocatedBlocksAndGetLastBlockLength();
      int retriesForLastBlockLength = dfsClient.getConf().retryTimesForGetLastBlockLength;
      while (retriesForLastBlockLength > 0) {
        // Getting last block length as -1 is a special case. When cluster
        // restarts, DNs may not report immediately. At this time partial block
        // locations will not be available with NN for getting the length. Lets
        // retry for 3 times to get the length.
        if (lastBlockBeingWrittenLength == -1) {
          DFSClient.LOG.warn("Last block locations not available. "
              + "Datanodes might not have reported blocks completely."
              + " Will retry for " + retriesForLastBlockLength + " times");
          waitFor(dfsClient.getConf().retryIntervalForGetLastBlockLength);
          lastBlockBeingWrittenLength = fetchLocatedBlocksAndGetLastBlockLength();
        } else {
          break;
        }
        retriesForLastBlockLength--;
      }
      if (retriesForLastBlockLength == 0) {
        throw new IOException("Could not obtain the last block locations.");
      }
    }
  }

1.7 进入fetchLocatedBlocksAndGetLastBlockLength()方法

  private long fetchLocatedBlocksAndGetLastBlockLength() throws IOException {
    //此处又出现了dfsClient,该对象负责与NameNode通信,由此可知getLocatedBlocks()方法实现了远程通信
    final LocatedBlocks newInfo = dfsClient.getLocatedBlocks(src, 0);
    if (DFSClient.LOG.isDebugEnabled()) {
      DFSClient.LOG.debug("newInfo = " + newInfo);
    }
    if (newInfo == null) {
      throw new IOException("Cannot open filename " + src);
    }

    if (locatedBlocks != null) {
      Iterator<LocatedBlock> oldIter = locatedBlocks.getLocatedBlocks().iterator();
      Iterator<LocatedBlock> newIter = newInfo.getLocatedBlocks().iterator();
      while (oldIter.hasNext() && newIter.hasNext()) {
        if (! oldIter.next().getBlock().equals(newIter.next().getBlock())) {
          throw new IOException("Blocklist for " + src + " has changed!");
        }
      }
    }
    locatedBlocks = newInfo;
    long lastBlockBeingWrittenLength = 0;
    if (!locatedBlocks.isLastBlockComplete()) {
      final LocatedBlock last = locatedBlocks.getLastLocatedBlock();
      if (last != null) {
        if (last.getLocations().length == 0) {
          if (last.getBlockSize() == 0) {
            // if the length is zero, then no data has been written to
            // datanode. So no need to wait for the locations.
            return 0;
          }
          return -1;
        }
        final long len = readBlockLength(last);
        last.getBlock().setNumBytes(len);
        lastBlockBeingWrittenLength = len; 
      }
    }

    fileEncryptionInfo = locatedBlocks.getFileEncryptionInfo();

    return lastBlockBeingWrittenLength;
  }

1.8 进入getLocatedBlocks(String src, long start)方法

  public LocatedBlocks getLocatedBlocks(String src, long start)
      throws IOException {
    return getLocatedBlocks(src, start, dfsClientConf.prefetchSize);
  }

进入getLocatedBlocks(String src, long start, long length)方法

  /*
   * This is just a wrapper around callGetBlockLocations, but non-static so that
   * we can stub it out for tests.
   */
  @VisibleForTesting
  public LocatedBlocks getLocatedBlocks(String src, long start, long length)
      throws IOException {
    TraceScope scope = getPathTraceScope("getBlockLocations", src);
    try {
      //此处终于见到了namenode 
      return callGetBlockLocations(namenode, src, start, length);
    } finally {
      scope.close();
    }
  }

1.9 进入callGetBlockLocations()方法

进入callGetBlockLocations(ClientProtocol namenode,String src, long start, long length)方法

  /**
   * @see ClientProtocol#getBlockLocations(String, long, long)
   */
  static LocatedBlocks callGetBlockLocations(ClientProtocol namenode,
      String src, long start, long length) 
      throws IOException {
    try {
      //调用namenode对象,进行远程调用
      return namenode.getBlockLocations(src, start, length);
    } catch(RemoteException re) {
      throw re.unwrapRemoteException(AccessControlException.class,
                                     FileNotFoundException.class,
                                     UnresolvedPathException.class);
    }
  }

callGetBlockLocations(ClientProtocol namenode,String src, long start, long length)方法涉及RPC的远程调用,后面再继续研读。

作者:chengyuqiang 发表于2017/11/26 17:52:41 原文链接
阅读:8 评论:0 查看评论

Kali Linux虚拟机安装完整安装过程及简单配置(视频)

$
0
0

Kali Linux虚拟机安装完整安装过程及简单配置

点击上述视频播放

作者:wy_bk 发表于2017/11/26 18:09:32 原文链接
阅读:15 评论:0 查看评论

BZOJ1816(Cqoi2010)[扑克牌]--二分答案

$
0
0

【链接】
bzoj1816

【解题报告】

二分答案,然后验证就行了。

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=55;
int n,m,L,R,a[maxn];
bool Check(int x)
{
    int t=min(x,m);
    for (int i=1; i<=n; i++)
    {
        if (a[i]<x) t-=x-a[i];
        if (t<0) return 0;
    }
    return 1;
}
int main()
{
    freopen("1816.in","r",stdin);
    freopen("1816.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++) scanf("%d",&a[i]);
    L=0; R=1000000000;
    while (L<=R)
    {
        int mid=(R-L>>1)+L;
        if (Check(mid)) L=mid+1; else R=mid-1;
    }
    printf("%d",R);
    return 0;
}
作者:CHNWJD 发表于2017/11/26 18:47:29 原文链接
阅读:71 评论:0 查看评论

ELK之Filebeat安装与配置及使用

$
0
0

1 Filebeat介绍

轻量型日志采集器。当您要面对成百上千、甚至成千上万的服务器、虚拟机和容器生成的日志时,请告别 SSH 吧。Filebeat 将为您提供一种轻量型方法,用于转发和汇总日志与文件,让简单的事情不再繁杂。


2 安装

# wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.0.0-linux-x86_64.tar.gz
# tar zxf filebeat-6.0.0-linux-x86_64.tar.gz -C /Data/apps/

3 应用一:Filebeat采集数据,写入到logstash

3.1 修改Filebeat配置

101.1.21.170是logstash机器的ip。

# cd /Data/apps/filebeat-6.0.0/
# sudo vi filebeat.yml

filebeat.prospectors:
enabled: true
-  /Data/apps/nginx/logs/access-filebeat-test.log
output.logstash:
hosts: ["101.1.21.170:5044"]


启动Filebeat
# sudo ./filebeat -e -c filebeat.yml

3.2 logstash配置

101.1.21.170是logstash机器的ip。

# /Data/apps/logstash-6.0.0/bin
# sudo vi filebeat.conf


input {
    beats {
        port => 5044
    }
}


output {
    stdout {
        codec => "rubydebug"
    }
}



启动logstash
# ./logstash -f filebeat.conf


3.3 向/Data/apps/nginx/logs/access-filebeat-test.log追加信息

# echo "CleverCode is coding" >> /Data/apps/nginx/logs/access-filebeat-test.log




4 应用二:Filebeat采集数据,写入到redis,然后logstash从reids队列中拉取数据

4.1 filebeat配置

# cd /Data/apps/filebeat-6.0.0/
# sudo vi filebeat.yml
filebeat.prospectors:
	 enabled: true
	 -  /Data/apps/nginx/logs/access-filebeat-test.log
output.redis:
     hosts: ["10.1.20.170"]
     port: 6379
     key: "filebeat"
     db: 0
     timeout: 5
	 

启动Filebeat
# sudo ./filebeat -e -c filebeat.yml




4.2 logstash配置

# /Data/apps/logstash-6.0.0/bin
# sudo vi redis.conf
input {
    redis {
        host => "10.1.20.170"
        port => 6379
        key => "filebeat"
        data_type => "list"
    }
}
output {
    stdout {
        codec => rubydebug
    }
}



启动logstash
# ./logstash -f redis.conf


4.3 向/Data/apps/nginx/logs/access-filebeat-test.log追加信息

# echo "this msg is from reids" >> /Data/apps/nginx/logs/access-filebeat-test.log 


作者:CleverCode 发表于2017/11/26 19:05:07 原文链接
阅读:64 评论:0 查看评论

Aerospike rd记录的rec_props结构

$
0
0

rd的rec_props存放三部分记录属性内容:LDT信息、set name、keyd。这三部分内存空间是连续的,这里只是分割开来方便说明。

如果rd不是LDT类型,那么是不存放第一部分内容的,直接开始就是存放set name。

rd->rec_props的p_data存放LDT、set name和keyd,而size是p_data存放内容的总大小。

作者:yanzongshuai 发表于2017/11/26 19:24:48 原文链接
阅读:55 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>