模拟赛

  • Post author:
  • Post category:其他




树(tree)


题目描述


点此看题




n ≤ 1 0 5 n\leq 10^5






n













1



0










5












解法


以前是暴力水过去的,结果今天考到了加强版,然后就凉了

不难发现可以用线段树分别维护以



u u






u





为根的最长上升子序列和最长下降子序列,然后拼起来就可以了。

线段树的下标是开始位置的权值,可以快速算出



a [ u ] a[u]






a


[


u


]





为起始点的最长上升子序列和最长下降子序列。然后还要把子树的线段树合并上来,合并的时候可以更新一下答案(左右子树的子序列拼起来)





d f s dfs






d


f


s





的时候顺便算一下经过



a [ u ] a[u]






a


[


u


]





的子序列即可,时间复杂度



O ( n log ⁡ n ) O(n\log n)






O


(


n




lo

g





n


)




#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int M = 100005;
const int up = 100000;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,tot,cnt,ans,a[M],b[M],f[M],rt[M];
int mx[50*M][2],ls[50*M],rs[50*M];
struct edge
{
	int v,next;
	edge(int V=0,int N=0) : v(V) , next(N) {}
}e[2*M];
void ins(int &x,int l,int r,int id,int f,int t)
{
	if(!x) x=++cnt;
	mx[x][f]=max(mx[x][f],t);
	if(l==r) return ;
	int mid=(l+r)>>1;
	if(mid>=id) ins(ls[x],l,mid,id,f,t);
	else ins(rs[x],mid+1,r,id,f,t);
}
int ask(int x,int l,int r,int L,int R,int f)
{
	if(L>r || l>R || !x) return 0;
	if(L<=l && r<=R) return mx[x][f];
	int mid=(l+r)>>1;
	return max(ask(ls[x],l,mid,L,R,f),ask(rs[x],mid+1,r,L,R,f));
}
int merge(int x,int y)
{
	if(!x || !y) return x+y;
	ans=max(ans,max(mx[ls[x]][0]+mx[rs[y]][1],mx[rs[x]][1]+mx[ls[y]][0]));
	mx[x][0]=max(mx[x][0],mx[y][0]);
	mx[x][1]=max(mx[x][1],mx[y][1]);
	ls[x]=merge(ls[x],ls[y]);
	rs[x]=merge(rs[x],rs[y]);
	return x;
}
void dfs(int u,int fa)
{
	int lis=0,lds=0;
	for(int i=f[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(v==fa) continue;
		dfs(v,u);
		int t1=ask(rt[v],1,m,1,a[u]-1,0);
		int t2=ask(rt[v],1,m,a[u]+1,up,1);
		ans=max(ans,max(t1+lds,t2+lis)+1);
		lis=max(lis,t1);
		lds=max(lds,t2);
		rt[u]=merge(rt[u],rt[v]);
	}
	ins(rt[u],1,m,a[u],0,lis+1);
	ins(rt[u],1,m,a[u],1,lds+1);
}
int main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=b[i]=read();
	sort(b+1,b+1+n);
	m=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=n;i++)
		a[i]=lower_bound(b+1,b+m+1,a[i])-b;
	for(int i=1;i<n;i++)
	{
		int u=read(),v=read();
		e[++tot]=edge(v,f[u]),f[u]=tot;
		e[++tot]=edge(u,f[v]),f[v]=tot;
	}
	dfs(1,0);
	printf("%d\n",ans);
}



多项式(poly)


题目描述

给定多项式



f 1 ( x ) = ∑ i = 0 n a i ⋅ x i f_1(x)=\sum_{i=0}^na_i\cdot x^i







f










1


















(


x


)




=





















i


=


0









n





















a










i






























x










i












,有关于



f f






f





的递推式



f i ( x ) = b i f i − 1 ′ ( x ) + c i f i − 1 ( x ) f_i(x)=b_if_{i-1}'(x)+c_if_{i-1}(x)







f










i


















(


x


)




=









b










i



















f











i





1






























(


x


)




+









c










i



















f





















版权声明:本文为C202044zxy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。