SPOJ COT2

题目:

    

Description

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.

Input

In the first line there are two integers N and M.(N<=40000,M<=100000)

In the second line there are N integers.The ith integer denotes the weight of the ith node.

In the next N-1 lines,each line contains two integers u v,which describes an edge (u,v).

In the next M lines,each line contains two integers u v,which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.

Output

For each operation,print its result.

Example

Input:           
8 5
8 2 105 2 9 3 8 5 7 7 1 2 1 3 1 4 3 5 3 6 3 7 4 8
2 5
7 8
Output: 4
<p>You are given a tree with <strong>N</strong> nodes.The tree nodes are numbered from <strong>1</strong> to <strong>N</strong>.Each node has an integer weight.</p>
<p>We will ask you to perfrom the following operation:</p>
<ul>
<li><strong>u v k</strong> : ask for the kth minimum weight on the path from node <strong>u</strong> to node <strong>v</strong></li>
</ul>
<p> </p>
<h3>Input</h3>
<p>In the first line there are two integers <strong>N</strong> and <strong>M</strong>.(<strong>N,M</strong><=100000)</p>
<p>In the second line there are <strong>N</strong> integers.The ith integer denotes the weight of the ith node.</p>
<p>In the next <strong>N-1</strong> lines,each line contains two integers <strong>u</strong> <strong>v</strong>,which describes an edge (<strong>u</strong>,<strong>v</strong>).</p>
<p>In the next <strong>M</strong> lines,each line contains three integers <strong>u</strong> <strong>v</strong> <strong>k</strong>,which means an operation asking for the kth minimum weight on the path from node <strong>u</strong> to node <strong>v</strong>.</p>
<h3>Output</h3>
<p>For each operation,print its result.</p>
<h3>Example</h3>
<pre><strong>Input:</strong>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 320px; 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">8 5</div>8 5
105 2 9 3 8 5 7 7
1 2        
1 3
1 4
3 5
3 6
3 7
4 8<br />2 5 1<br />2 5 2<br />2 5 3<br />2 5 4<br />7 8 2 </pre>
<pre><strong>Output:</strong>
2<br />8<br />9<br />105<br />7 </pre>

网上大概看到两种解法,一种是:http://blog.csdn.net/kuribohg/article/details/41458639 

                                        用xor 思想求得

再一种就是这种直接求得:http://blog.csdn.net/u013598409/article/details/44943851 

我说第二种:

先ORZ 这位博主的代码 :

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 const int N=40001;
  9 const int M=161121;
 10 const int K=16;
 11 
 12 struct R
 13 {
 14     int d,id;
 15 }rk[N];
 16 int n,m,w[N];
 17 struct G
 18 {
 19     int v,nxt;
 20 }map[N<<1];
 21 int tot,hd[N];
 22 int in[N],out[N],lst[N<<1],num;
 23 int pre[K+2][N],dep[N];
 24 struct Q
 25 {
 26     int l,r,anc,id;
 27 }q[M];
 28 int v[N],unit,res,l,r,has[N],ans[M];    //注意ans的数据范围,为询问的个数
 29 
 30 inline void ins(int u,int v)
 31 {
 32     map[++tot].v=v;
 33     map[tot].nxt=hd[u];
 34     hd[u]=tot;
 35 }
 36 
 37 void DFS(int now,int high)
 38 {
 39     dep[now]=high;
 40     in[now]=++num;
 41     lst[num]=now;
 42 
 43     for (int k=hd[now];k;k=map[k].nxt)
 44         if (!dep[map[k].v])
 45         {
 46             DFS(map[k].v,high+1);
 47             pre[0][map[k].v]=now;
 48         }
 49 
 50     out[now]=++num;
 51     lst[num]=now;
 52 }
 53 
 54 inline int cmp1(R a,R b)
 55 {
 56     return a.d<b.d;
 57 }
 58 
 59 void init(void)
 60 {
 61     scanf("%d%d",&n,&m);
 62     for (int i=1;i<=n;i++) scanf("%d",&w[i]);
 63 
 64     int tmp,cnt;
 65     for (int i=1;i<=n;i++) rk[i].d=w[i],rk[i].id=i;
 66     sort(rk+1,rk+n+1,cmp1);
 67     tmp=rk[1].d,w[rk[1].id]=cnt=1;
 68     for (int i=2;i<=n;i++)
 69     {
 70         if (tmp^rk[i].d) tmp=rk[i].d,cnt++;
 71         w[rk[i].id]=cnt;
 72     }
 73 
 74     int x,y;
 75     for (int i=1;i<n;i++)
 76     {
 77         scanf("%d%d",&x,&y);
 78         ins(x,y),ins(y,x);
 79     }
 80 
 81     pre[0][1]=1;
 82     DFS(1,1);
 83 
 84     for (int i=1;i<=K;i++)
 85         for (int j=1;j<=n;j++)
 86             pre[i][j]=pre[i-1][pre[i-1][j]];
 87 }
 88 
 89 inline int cmp(Q a,Q b)
 90 {
 91     return a.l/unit!=b.l/unit?a.l/unit<b.l/unit:a.r<b.r;
 92 }
 93 
 94 inline int min(int i,int j)
 95 {
 96     return i<j?i:j;
 97 }
 98 
 99 inline int max(int i,int j)
100 {
101     return i>j?i:j;
102 }
103 
104 inline int LCA(int x,int y)
105 {
106     if (dep[x]>dep[y]) x^=y^=x^=y;
107     for (int i=K;i+1;i--)
108         if (dep[y]-dep[x]>=1<<i) y=pre[i][y];
109     if (x==y) return x;                            //注意特判x=y时的LCA就是x=y
110     for (int i=K;i+1;i--)
111         if (pre[i][x]^pre[i][y])
112             x=pre[i][x],y=pre[i][y];
113     return pre[0][x];
114 }
115 
116 inline void solve(int i)        //"有无"时的写法
117 {
118     if (has[lst[i]])
119     {
120         v[w[lst[i]]]--;
121         if (!v[w[lst[i]]]) res--;
122         has[lst[i]]=0;
123     }
124     else
125     {
126         if (!v[w[lst[i]]]) res++;
127         v[w[lst[i]]]++;
128         has[lst[i]]=1;
129     }
130 }
131 
132 void work(void)
133 {
134     int x,y;
135     unit=(int)sqrt(num);            //num instead of n
136     for (int i=1;i<=m;i++)
137     {
138         scanf("%d%d",&x,&y);
139         q[i].id=i;
140         if (x==y) q[i].anc=-1;
141         else
142         {
143             q[i].anc=LCA(x,y);
144             if (q[i].anc!=x&&q[i].anc!=y)
145             {
146                 q[i].l=min(out[x],out[y]);
147                 q[i].r=max(in[x],in[y]);
148             }
149             else
150             {
151                 q[i].l=min(in[x],in[y]);
152                 q[i].r=max(in[x],in[y]);
153             }                                //(1)相同        (2)有1个为LCA:两个in    (3) 都不同:max(in)&&min(out)
154         }
155     }
156     sort(q+1,q+m+1,cmp);        //注意用id弄到ans,不能直接输出
157 
158     l=1,r=0;
159     for (int i=1;i<=m;i++)
160         if (q[i].anc==-1) ans[q[i].id]=1;
161         else
162         {
163             for (;l<q[i].l;l++) solve(l);
164             for (;q[i].l<l;l--)    solve(l-1);
165             for (;r<q[i].r;r++) solve(r+1);
166             for (;q[i].r<r;r--) solve(r);
167             if (lst[q[i].l]==q[i].anc||lst[q[i].r]==q[i].anc)    //注意加上lst
168                 ans[q[i].id]=res;
169             else
170             {
171                 solve(in[q[i].anc]);
172                 ans[q[i].id]=res;
173                 solve(in[q[i].anc]);
174             }
175         }
176 
177     for (int i=1;i<=m;i++) printf("%d ",ans[i]);
178 }
179 
180 int main(void)
181 {
182     init();
183     work();
184 
185     return 0;

186 } 

原文地址:https://www.cnblogs.com/forgot93/p/4788311.html