SPOJ COT2

【标签】离散化,数据结构,分治,图论

【题意】

You are given a tree with N nodes.

The tree nodes are numbered from 1 to N.

Each node has an integer weight.

We will ask you to perfrom the following operation:

u v : ask for how many different integers that represent the weight of nodes there are on the path from u to v.

【分析】

首先离散化,把w转化一下,开始看到integer以为是-32768和32767间的整数,直接开桶存储,然后就悲剧地挂掉了...

然后DFS一遍,lst保存入和出的总序列,in保存第i个点入的编号,out保存出的编号

对于路径:树上倍增求LCA

对于问题:树上莫队。

(1)若x=y答案就是1

(2)若LCA(x,y)=x或y则左端点为min(in[x],in[y]),右端点为max(in[x],in[y])

(3)若都不同则左端点为min(out[i],out[j]),右为max(in[i],in[j]),这是可以证明的。

然后用莫队算法排序预处理,直接暴力,暴力时要用has[N]表示这个节点有没有被访问,开v[N]存储每个元素有多少个,然后访问一个节点has[N]就 xor 1。

注意要按照题目的顺序输出答案,开ans记录每个答案就是了

下面的代码有相关易错点...

【实现】

#include 
#include 
#include 
#include 
#include 
using namespace std;

const int N=40001;
const int M=161121;
const int K=16;

struct R
{
	int d,id;
}rk[N];
int n,m,w[N];
struct G
{
	int v,nxt;
}map[N<<1];
int tot,hd[N];
int in[N],out[N],lst[N<<1],num;
int pre[K+2][N],dep[N];
struct Q
{
	int l,r,anc,id;
}q[M];
int v[N],unit,res,l,r,has[N],ans[M];	//注意ans的数据范围,为询问的个数 

inline void ins(int u,int v)
{
	map[++tot].v=v;
	map[tot].nxt=hd[u];
	hd[u]=tot;
}

void DFS(int now,int high)
{
	dep[now]=high;
	in[now]=++num;
	lst[num]=now;
	
	for (int k=hd[now];k;k=map[k].nxt)
		if (!dep[map[k].v])
		{
			DFS(map[k].v,high+1);
			pre[0][map[k].v]=now;
		}
	
	out[now]=++num;
	lst[num]=now;
}

inline int cmp1(R a,R b)
{
	return a.dj?i:j;
}

inline int LCA(int x,int y)
{
	if (dep[x]>dep[y]) x^=y^=x^=y;
	for (int i=K;i+1;i--)
		if (dep[y]-dep[x]>=1<


【小结】

(1) 树上倍增

(2) 树上莫队"有无"的写法,注意3种情况的分类讨论

(3) 排序后的结果要开ans[M]按序输出

(4) Integer是整数的意思,不是-32768--32767。。。

你可能感兴趣的:(SPOJ)