切记不要加任何文件读写, 本次比赛暂不支持ifndef ONLINE_JUDGE。请互相转告。评测机是linux
是个富有诗意的男孩。在他居住的小镇上,有 n个村庄,由 n-1条道路连接着。这里的生活和谐而又宁静。
有一天 tty偶然阅读到一篇杂志上的文章《阳光下的向日葵》,深受感动。特别是其中一位小女孩的故事让他记忆犹新。 于是他买来葵花籽,决定也像那位小女孩一样,给村民播种向日葵,把美丽和阳光带给村庄里的每一个人。
于是 tty决定在每次播种前选择两个村庄,然后从其中一个村庄出发,在这两个村庄的道路上的每一个村庄(包括起始点)种上一颗向日葵,在编号 i的村庄播种在可以长出 wi个葵花籽,而且向日葵受到天神 Owaski的保护,在生长过程中不会被人采摘。
若干天后,待到向日葵成熟时,tty又会以相同的路径去采摘那些向日葵上的葵花籽, 无论是否采摘,每一次播种的向日葵都会在下一次播种前死亡。
但是有轻微强迫症的他,不会采摘比他采摘的上一朵葵花籽相等或者更少的向日葵。
而tty并不知道这些数据,只能凭着感觉开始采摘,他想在更多的向日葵上采摘葵花籽,你能告诉他可以最多采摘的向日葵棵数吗?
题解:n个点n-1条边显然是一棵树嘛,所以每个询问求的是树上两点之间权值序列的LIS。
考场上我先是转有根树,求LCA然后暴力找路径nlogn求LIS(其实不需要这么麻烦),结果爆0了。
正确的姿势应该是离线算法,也就是预处理出答案ans[i][j],询问就O(1)输出。
首先枚举每个点,DFS求出这个点与其它点的LIS。这就是加点地求LIS。如果这个点的权值大于栈顶元素的话直接压栈更新答案。否则二分查找第一个权值大于等于它的并将其替换再维护答案。回溯回来要记得改回。这样的时间复杂度是O(n^2logn+Q)的。记得无向图边数要乘2。
%%%__debug大神。
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define INF 0x7fffffff/10
#define x first
#define y second
using namespace std;
const int MAXN=4002;
int first[MAXN],next[MAXN],w[MAXN],e=0,v[MAXN],n,q=0,f[MAXN];
int top=0,ans[MAXN][MAXN],d[MAXN];
struct point{
int x,y;
point(int x=0,int y=0):x(x),y(y){}
bool operator <(const point& rhs)const {return x<rhs.x;}
}sta[MAXN];
void add(int a,int b)
{
e++;next[e]=first[a];first[a]=e;v[e]=b;
}
void dfs(int u,int fa,int from,int last)
{
for(int i=first[u];i!=-1;i=next[i])
{
int to=v[i],ty=0,lc,la,lb,anss=last;
if(to==fa)continue;
if(from==2&&to==7)
to=7;
if(w[to]>sta[top].x)
{
anss=max(anss,top+1);
f[to]=++top;
sta[top].y=to;
sta[top].x=w[to];
ty=1;
}
else
{
int k=lower_bound(sta+1,sta+top+1,point(w[to],to))-sta;
f[to]=k;
anss=max(anss,k);
lc=k;la=sta[k].x;lb=sta[k].y;
sta[k].x=w[to];
sta[k].y=to;
}
ans[from][to]=anss;
dfs(to,u,from,anss);
if(ty)top--;
else
{
sta[lc].x=la;
sta[lc].y=lb;
}
}
}
int main()
{
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<=n;i++)first[i]=-1;
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d %d",&a,&b);
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
for(int i=1;i<=n;i++)
{
top=1;
ans[i][i]=1;
sta[top].y=i;
sta[top].x=w[i];
dfs(i,-1,i,1);
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
int a,b;
scanf("%d %d",&a,&b);
printf("%d\n",ans[a][b]);
}
return 0;
}