HDU4718 – The LCIS on the Tree(LCT)

HDU4718

【题意】求树上任意两点u->v的LIS;

【分析】可以用树链剖分,不过最近在练LCT,就用LCT来写,维护区间信息很简单,只要注意下LCT最后求上来的时候是lca->u,lca->v,lca;所以需要维护一个从后往前的LIS值。第一次写LCT 1A,好开心(七夕宅在家调了一上午,有点郁闷)。

【AC CODE】1201ms

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define ls ch[u][0]
#define rs ch[u][1]
const int INF = 0x3f3f3f3f, MAXN = 100000+10;
int par[MAXN],fa[MAXN],ch[MAXN][2],val[MAXN];
int mx[MAXN][2],lsum[MAXN][2],lv[MAXN],rsum[MAXN][2],rv[MAXN],sz[MAXN];

void init()
{
	clc(par,0);clc(fa,0);clc(ch,0);
}
inline int chd(int u){return ch[fa[u]][1] == u;}
inline void setch(int f, int u, int d){ch[f][d] = u, fa[u] = f;}
inline void push_up(int u)
{
	//l->r
	mx[u][0] = max(mx[ls][0],mx[rs][0]);
	if(!ls || rv[ls] < val[u])
	{
		mx[u][0] = max(mx[u][0],rsum[ls][0]+1);
		if(val[u] < lv[rs]) mx[u][0] = max(mx[u][0],rsum[ls][0]+1+lsum[rs][0]);
	}
	if(val[u] < lv[rs]) mx[u][0] = max(mx[u][0],1+lsum[rs][0]);
	lsum[u][0] = lsum[ls][0];
	if(lsum[ls][0] == sz[ls])
	{
		if(!ls || rv[ls] < val[u])
		{
			lsum[u][0]++;
			if(val[u] < lv[rs]) lsum[u][0] += lsum[rs][0];
		}
	}
	rsum[u][0] = rsum[rs][0];
	if(rsum[rs][0] == sz[rs])
	{
		if(!rs || val[u] < lv[rs])
		{
			rsum[u][0]++;
			if(rv[ls] < val[u]) rsum[u][0] += rsum[ls][0];
		}
	}
	//r->l
	mx[u][1] = max(mx[ls][1],mx[rs][1]);
	if(!rs || lv[rs] < val[u])
	{
		mx[u][1] = max(mx[u][1],lsum[rs][1]+1);
		if(val[u] < rv[ls]) mx[u][1] = max(mx[u][1],lsum[rs][1]+1+rsum[ls][1]);
	}
	if(val[u] < rv[ls]) mx[u][1] = max(mx[u][1],1+rsum[ls][1]);
	lsum[u][1] = lsum[ls][1];
	if(lsum[u][1] == sz[ls])
	{
		if(!ls || val[u] < rv[ls])
		{
			lsum[u][1]++;
			if(lv[rs] < val[u]) lsum[u][1] += lsum[rs][1];
		}
	}
	rsum[u][1] = rsum[rs][1];
	if(rsum[u][1] == sz[rs])
	{
		if(!rs || lv[rs] < val[u])
		{
			rsum[u][1]++;
			if(val[u] < rv[ls]) rsum[u][1] += rsum[ls][1];
		}
	}

	lv[u] = ls?lv[ls]:val[u],rv[u] = rs?rv[rs]:val[u];
	sz[u] = sz[ls]+sz[rs]+1;
}
inline void rot(int u)
{
	int d = chd(u),y = fa[u];
	setch(fa[y],u,chd(y));
	setch(y,ch[u][d^1],d);
	setch(u,y,d^1);
	push_up(y);push_up(u);
}
void splay(int u)
{
	int rt = u;
	while(fa[rt]) rt = fa[rt];
	if(rt == u) return;
	par[u] = par[rt],par[rt] = 0;
	while(fa[u])
	{
		if(fa[fa[u]] && chd(u) == chd(fa[u])) rot(fa[u]);
		rot(u);
	}
}
void expose(int u)
{
	for(int now = u,la = 0;now;la = now,now = par[now])
	{
		splay(now);
		par[ch[now][1]] = now;fa[ch[now][1]] = par[la] = 0;
		setch(now,la,1);
		push_up(now);
	}
	splay(u);
}
int query(int u, int v)
{
	expose(u);
	for(int now = v,la = 0;now;la = now,now = par[now])
	{
		splay(now);
		if(!par[now])
		{
			int l = ch[now][1],r = la;
			int ans = max(max(mx[l][1],mx[r][0]),1);
			if(lv[l] < val[now])
			{
				ans = max(ans,lsum[l][1]+1);
				if(val[now] < lv[r]) ans = max(ans,lsum[l][1]+1+lsum[r][0]);
			}
			if(val[now] < lv[r]) ans = max(ans,1+lsum[r][0]);
			return ans;
		}
		par[ch[now][1]] = now;fa[ch[now][1]] = par[la] = 0;
		setch(now,la,1);
		push_up(now);
	}
}

int main()
{
#ifdef SHY
	freopen("d:\\1.txt", "r", stdin);
#endif
	int t,count = 0;
	scanf("%d", &t);
	while(t--)
	{
		init();
		int n;
		scanf("%d", &n);
		repe(i,1,n)
		{
			scanf("%d", &val[i]);
			lv[i] = rv[i] = val[i];
			mx[i][0] = mx[i][1] = lsum[i][0] = lsum[i][1] = rsum[i][0] = rsum[i][1] = sz[i] = 1;
		}
		repe(i,2,n) scanf("%d", &par[i]);
		int q;
		if(count++) putchar('\n');
		printf("Case #%d:\n",count);
		scanf("%d", &q);
		while(q--)
		{
			int u,v;
			scanf("%d %d", &u, &v);
			printf("%d\n", query(u,v));
		}
	}
	return 0;
}

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

请输入正确的验证码