专栏文章
题解:P6534 [COCI 2015/2016 #1] UZASTOPNI
P6534题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mipapukp
- 此快照首次捕获于
- 2025/12/03 08:55 3 个月前
- 此快照最后确认于
- 2025/12/03 08:55 3 个月前
思路
这道题是一道十分巧妙的树形DP。
其中 表示以结点 为根的子树当中,等差数列的首项为 是否可行。 表示已结点 为根的子树中等差数列末项为 为根是否可行。其中 中的 要满足 , 中的 要满足 (题目要求当选了一个结点后必须选它的上司,与就是父亲结点)。
那对于 需要 的一个子节点 中 。然后发现,如果想要让 ,还需要让 的整颗子树能与 组成等差数列,并且必须是与笑话编号比 小的组成,不然它就无法成为等差数列的首项。既然必须是 的首项,那 中就必须是末项。
对于 是一样的,只需把上面全都反过来。
Code
CPP#include<bits/stdc++.h>
using namespace std;
int n,v[20000],h[20000],ne[20000],e[20000],idx,l[20000][200],r[20000][200];
void add(int u,int v){
e[idx]=v,ne[idx]=h[u],h[u]=idx++;
}
void dfs(int x){
vector<int> tl,tr;
for(int i=h[x];~i;i=ne[i]){
int j=e[i];
dfs(j);
if(v[j]<v[x]) tl.push_back(j);
if(v[j]>v[x]) tr.push_back(j);
}
l[x][v[x]]=1,r[x][v[x]]=1;
for(int i=v[x]-1;i>=1;i--){
for(auto p:tl){
if(l[p][i]){
for(int j=i;j<v[x];j++){
if(r[p][j]&&l[x][j+1]){
l[x][i]=1;
break;
}
}
}
}
}
for(int i=v[x]+1;i<=100;i++){
for(auto p:tr){
if(r[p][i]){
for(int j=v[x]+1;j<=i;j++){
if(l[p][j]&&r[x][j-1]){
r[x][i]=1;
break;
}
}
}
}
}
}
int main(){
memset(h,-1,sizeof(h));
cin>>n;
for(int i=1;i<=n;i++){
cin>>v[i];
}
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
add(u,v);
}
dfs(1);
int lans=0,rans=0;
for(int i=1;i<=100;i++){
lans+=l[1][i];
rans+=r[1][i];
}
cout<<lans*rans;
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...