AC题目简解-数据结构

A - Japan  POJ 3067 
要两条路有交叉,(x1,y1)(x2,y2)那么需要满足:(x1-x2)*(y1-y2)<0判断出这是求逆序的问题 
树状数组求逆序,先通过自定义的比较器实现按照一种元素排序,然后再逐次查询和add来获取结果

B - Ping pong POJ 3928 
分析裁判的位置,则可判断求逆序问题。对每个点的裁判,他能举办的比赛场数为左弱*右强+左强*右弱,通过正序和倒序两次插入和查询累加得最终结果

C - Balanced Lineup POJ 3274 
用线段树A的==

D - Mobile phones POJ 1195 
二维树状数组,理解了一维的,二维的也很好理解。一维是前面线上的和,二维的是前面矩形的和。算目标范围也很明确,就是减掉两个矩形的加上多减的一个正方形,维护跟一维的也基本一样

E - MooFest POJ 1990 
首先,最重要的是理解好题意:1.两头牛只要通讯一次就行。每次的耗费是distance*max(v[i],v[j])2.按power还是按position排序。我选的是power,因为position没有重复值。排序这个想法跟Japan那道题是一样的。 
说下思路: 
按照power的升序排好后,依次加入树状数组,每加一次,就查一次,累计一次ans。这个是标准的数组数组的解法。 
但是,树状数组的索引值是牛的坐标的索引值,这就意味着,能力比当前低的牛可能会排到其后面,而且,它们的距离值是需要的。 
这就要求,既能记录到前面有多少头牛,又能记录他们的距离和,后面有多少头牛,和他们的距离和。 
而想到,加点的时候,有一个i来控制,也就是说,在i前面   有    a头牛的话,后面有i-a头,顺着这个想法,那也可以统计坐标和啊。前面加了i头牛,总共的坐标和distance可以累加出来,而在i的坐标前面有(这里的有和加是两回事)的牛的坐标和为sum(data[i].position-1).dist,那么坐标在第i个的后面,而且power比第i个的小的坐标和就是distance-sum(data[i].position-1).dist 
因为是按照power排的序,所以在i前面加的power都比第i个小,也就是说,如果之前加的和第i个通讯的话,取的power指肯定是第i个的 
公式: 
这里的sum(data[i].position).num表示坐标在data[i].position前面的牛的个数 
sum(data[i].position-1).dist    i的坐标前面有(这里的有和加是两回事)的牛的坐标和

ans+=(sum(data[i]-1).num*data[i].position - sum(data[i].position-1).dist + (distance-sum(data[i].position-1).dist - (i-1-sum(data[i]-1).num)*data[i].position ))*data[i].power 
可以化简为 
int x1=sum(data[i]-1).num,x2=sum(data[i].position-1).dist; 
ans+=(data[i].position*(x1*2-i+1) - x2*2 + distance)*data[i].power;

然后distance累加再把当前点add进树状数组就ok了

A-敌兵布阵 hdu 1166
标准的线段树 小细节:a*2+1  =  a<<1|1
开空间的时候,要开MAX<<2
switch(x){
case 1:  ... break;
}

B - I Hate It HDU 1754
基本和A没有很大的区别,只是和变成了最大值

C - A Simple Problem with Integers  HDU 3468
线段树区间更新,模板
lazy标记
注意:pushup()出现在:build()的最后,updata()的最后

D - Count Color POJ 2777
线段树的灵活应用和位运算的技巧
很容易想到用key来存染的颜色,存的技巧:位运算(学习笔记)
区间点的key则可以通过左右孩子的或运算来获得。注意,按照二进制的方法传进颜色的时候,传的是处理过的color

E - Hotel POJ 3667
询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并
查询的时候:
if(左儿子的center >= 要查询的长度)return 在左儿子查询
else 
if(左儿子的右+右儿子的左 >=要查询的长度)return 左儿子的左的起始坐标
else return 在右儿子查询
pushup的时候:
如果左儿子是空的,那么节点的左=左儿子+右儿子的左
如果右儿子是空的,那么节点的右=右儿子+左儿子的右
节点的center=max(左右儿子的center,左儿子的右加上右儿子的左)
其他就是一些细节问题了,不要把自己搞混就好

F - Holedox Eating HDU 4302
小虫子吃蛋糕,注意几个要点:1.虫子会采取就近原则,如果等距就按原来的方向2可能会没有蛋糕
线段树版:
左右来存此区间最左端和最右端的蛋糕的坐标,pushup的时候有以下情况:1左右儿子都空,那就都空2左儿子空,右儿子非空,3左儿子非空,右儿子空和非空 共四种
查询的时候:1左右儿子有一个空,那就再另一个里查找,都空的情况在query以前就判断2距左儿子的右  与  距右儿子的左 ,跟谁近就query哪个,等距就按原方向
一些细节:从0开始的,可以把题目中的坐标都+1
TreeSet版:
一个set存有蛋糕的坐标,利用higher和lower方法来找到左右值,然后比较之。

总结:
线段树问题:单点更新、区间更新、区间查询、区间染色、吃蛋糕问题、区间连续长度查询

A - Language of FatMouse  ZOJ1109
TreeMap的应用,映射,左边是key,右边是value,一般情况下以key为主
TreeMap<String, String> map=new TreeMap<String,String>();这里记得第二个<>也要填好
containsKey、get、put 和 remove 操作提供受保证的 log(n) 时间开销 
B - For Fans of Statistics  URAL 1613 
二叉查找树,由于一个key可能有多个value,所以TreeMap<Integer, TreeSet<Integer>> map = new TreeMap<Integer, TreeSet<Integer>>();查找的时候注意一些小的优化if (x != null && x.ceiling(l) != null && x.ceiling(l) <= r)
快速io的使用,见学习笔记。
C - Hardwood Species POJ 2418
words statistics TreeMap的简单应用,TreeMap会自动去重,新的会覆盖旧的映射。主要是遍历的方法。见学习笔记。
输出时,java中也有printf,类似C++,格式基本一样。"%.4f"保留四位小数
D - Station
TreeSet的技巧应用
add 和del 都只涉及左右的点,从这里出发,考虑存点,用TreeSet。而在del时暴力遍历一遍找最小的距离。
E - Web Navigation ZOJ 1061
模拟浏览器的操作,关键是题目信息提取的准确性。当前的页面和在back栈顶的页面不一回事。还有forward.clear
F - Argus ZOJ 2212
这题直接交的以前的代码==
不过还挺重要的。要自己写PriorityQueue的Comparator。这个在学习笔记里。
优先级队列,已经封装好的add等,主要思路就是每个period都自己累加,加进队列以后又能是有序的。
G - Plug-in
字符串去重,栈即可。只是在最后的时候,pop的速度非常慢,直接
for (char x : stack)
System.out.print(x);

上一篇:Java基础-Java中的堆内存和离堆内存机制


下一篇:windows 下 TensorFlow(GPU 版)的安装