SPOJ Count on a tree
Posted mxzf0213
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ Count on a tree相关的知识,希望对你有一定的参考价值。
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 perform the following operation:
- u v k : ask for the kth minimum weight on the path from node u to node v
Input
In the first line there are two integers N and M.(N,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 three integers u v k,which means an operation asking for the kth minimum weight on the path from node u to node v.
Output
For each operation,print its result.
Example
Input:
8 5 105 2 9 3 8 5 7 7 1 2 1 3 1 4 3 5 3 6 3 7 4 8
2 5 1
2 5 2
2 5 3
2 5 4
7 8 2
Output: 2
8
9
105
7
分析:tarjan+主席树,加了一下读入挂,挺快的;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <map> #include <queue> #include <stack> #include <vector> #include <list> #define rep(i,m,n) for(i=m;i<=n;i++) #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++) #define mod 1000000007 #define inf 0x3f3f3f3f #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define Lson L, mid, rt<<1 #define Rson mid+1, R, rt<<1|1 const int maxn=4e6+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;} int n,m,k,t,a[maxn],b[maxn],s[maxn],ls[maxn],rs[maxn],root[maxn],vis[maxn],ans[maxn],fa[maxn],h[maxn],g[maxn],sz,num,tot,tot1; struct node { int x,y,z; node(){} node(int _x,int _y,int _z):x(_x),y(_y),z(_z){}; }; struct node1 { int to,nxt; }e[maxn]; struct node2 { node p; int nxt; }f[maxn]; void add(int x,int y) { tot++; e[tot].to=y; e[tot].nxt=h[x]; h[x]=tot; } void add1(int x,int y,int z,int k) { tot1++; f[tot1].p=node(y,z,k); f[tot1].nxt=g[x]; g[x]=tot1; } inline ll read() { ll x=0;int f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void insert(int l,int r,int x,int &y,int v) { y=++sz; s[y]=s[x]+1; if(l==r)return; ls[y]=ls[x],rs[y]=rs[x]; int mid=l+r>>1; if(v<=mid)insert(l,mid,ls[x],ls[y],v); else insert(mid+1,r,rs[x],rs[y],v); } int gao(int l,int r,int x,int y,int z,int k,int care) { if(l==r)return l; int mid=l+r>>1,j; j=s[ls[y]]+s[ls[z]]-2*s[ls[x]]+(care>=l&&care<=mid); if(j>=k)return gao(l,mid,ls[x],ls[y],ls[z],k,care); else return gao(mid+1,r,rs[x],rs[y],rs[z],k-j,care); } void dfs(int now,int pre) { vis[now]=1; insert(1,num,root[pre],root[now],a[now]); for(int i=g[now];i;i=f[i].nxt) { node p=f[i].p; if(vis[p.y]) { int fa=find(p.y); ans[p.x]=b[gao(1,num,root[fa],root[now],root[p.y],p.z,a[fa])]; } } for(int i=h[now];i;i=e[i].nxt) { int to=e[i].to; if(!vis[to]) { dfs(to,now); fa[to]=now; } } } int main() { int i,j; scanf("%d%d",&n,&m); rep(i,1,n)a[i]=read(),b[i]=a[i],fa[i]=i; sort(b+1,b+n+1); num=unique(b+1,b+n+1)-b-1; rep(i,1,n)a[i]=lower_bound(b+1,b+num+1,a[i])-b; rep(i,1,n-1) { int c,d; c=read(),d=read(); add(c,d);add(d,c); } rep(i,1,m) { int c,d,k; c=read(),d=read(),k=read(); add1(c,i,d,k); add1(d,i,c,k); } dfs(1,0); rep(i,1,m)printf("%d\n",ans[i]); //system("Pause"); return 0; }
以上是关于SPOJ Count on a tree的主要内容,如果未能解决你的问题,请参考以下文章
spoj COT2 - Count on a tree II