POJ 1984 Navigation Nightmare(路径压缩并查集)
并查集,给n个点和m条边,每条边有方向和长度,再给q个询问,第i个询问查询两个点之间在Ti时刻时的曼哈顿距离(能连通则输出曼哈顿距离,否则输出-1
这题还要注意数据可能不是按照时间顺序输入的,要做按时间顺序由小到大排序,然后再按原来的顺序输出。还是路径压缩的一套不过这次有两个r[]数组,rx[i]表示i节点到父亲节点的x距离,ry[i]同理,输入m条边时,
for (i=1;i<=m;i++)
{
scanf("%d%d%d %c",&x[i],&y[i],&d,&c);
switch(c)
{
case 'W':dx[i]=-d;dy[i]=0;break;//西
case 'S':dx[i]=0;dy[i]=-d;break;
case 'E':dx[i]=d;dy[i]=0;break;
case 'N':dx[i]=0;dy[i]=d;break;
}
}
for (i=1;i<=k;i++)
{
for (;j<=a[i].idx;j++)
{
fx=find(x[j]);fy=find(y[j]);
fa[fy]=fx;
rx[fy]=rx[x[j]]-rx[y[j]]-dx[j];//到根节点的距离,fx在fy左边为负,右边为正
ry[fy]=ry[x[j]]-ry[y[j]]-dy[j];//上fx在fy上方
为正,下为负
}
if (find(a[i].x)!=find(a[i].y))
ans[a[i].n]=-1;
else
ans[a[i].n]=abs(rx[a[i].x]-rx[a[i].y])+abs(ry[a[i].x]-ry[a[i].y]);
}
POJ 2631 Roads in the North(树的直径)
求树上最长的两个点之间的距离。这里有一个结论,在图中,要找到距离最远的两点,先随便从一个点入手bfs,找到距离这个点最远的点,在从这个点bfs找到距离这点最远的点,这两点之间的距离就是这颗树的直径。即首先从树上任意一个点a出发, (BFS)找出到这个点距离最远的点b. 然后在从b点出发(BFS)找到距离b点最远的点c. 那么bc间的距离就是树的直径.所以直接进行bfs搜索就行了
poj 1985 Cow Marathon 【树的直径】
和上一道题目一样,裸题。
树状数组只能计算A[1]开始的和,A[0]这个元素是不能用的,复杂度O(logn)。执行n次add操作,总时间复杂度O(nlogn)。注意,刚开始c数组要初始全0,然后每读入一个数A[i]就执行一步add(i, A[i])来进行真正的初始化。
且树状数组处理的数组A[n]是从小标1开始的,也即A[0]是一个没有用的元素。
C数组中的每一个元素都是A数组中的一段连续和。
HDU 1166 敌兵布阵(简单树状数组)
树状数组裸题
UVA1428 Ping pong(树状数组)
先别想与树状数组有什么联系?先想拿到这个题目怎么做?很容易想到枚举谁可以当裁判,但裁判的条件是,假设c是裁判,a,b是对手,则a<=c<=b,即裁判能力值介于比赛者之间,且比赛选手是在裁判住所两侧各挑一个,不能都在同一侧,他当裁判时有几种比赛组织方式。对于第i个裁判,他能组织多少种比赛?
假设a1~a[i-1]有L个能力值比a[i]小的,那么比a[i]大的i-1-L个
A[i+1]~a[n]有R个能力值比a[i]小的,那么比a[i]大的有n-i-R个
··················i················
L个小于等于a[i] R个小于等于a[i]
i-1-L个比a[i]大 n-i-R个比a[i]大
显然,第i个裁判可以组织的比赛场数
L*(n-i-R)+(i-1-L)*R。
问题就转化成了,对于每个裁判怎么求其,L,R,这个地方就可以用树状数组了。
对每个i,求左边比他小的数,正着跑一边,这个数出现了,就在他的位置加1,对于每个数,先求一下比他小的有几个,再把这个数add进去。
对每个I,求右边比他小的数,倒着跑一边,这个输出现,就在他的位置+1,对于每个数,先求一下比他小的有几个,再把这个数add进去。
3 4 5 1 1 2为例
求左边
C数组
1位置 2位置 3位置 4位置 5位置
0 0 0 0 0
Sum(3)=0,显然左边比3小的没有
Add(3,1)
0 0 1 0 0
Sum(4)=1,显然左边比4小的有一个
Add(4,1)
0 0 1 1
Sum(5)=2,显然左边比5小的有两个
Add(5,1)
0 0 1 1 1]
Sum(1)=0,显然1左边小于等于它的没有
Add(1,1)
1 0 1 1 1
Sum(1)=1,显然1左边小于等于它的有一个
Add(1,1)
2 0 1 1 1
Sum(2)=2,显然2左边小于等于它的有2个
求右边类似
C数组
1位置 2位置 3位置 4位置 5位置
0 0 0 0 0
Sum(2)=0;
Add(2,1)
0 1 0 0 0
Sum(1)=0
Add(1,1)
1 1 0 0 0
Sum(1)=1
Add(1,1)
2 1 0 0 0
····