传送门

这题神坑啊……明明是你菜

首先大家都知道原题等价于给每个点分配一个$1$~$n$且两两不同的权值,同时还需要满足一些大于/小于关系的方案数。

先看一眼数据范围,既然写明了$n\le 1000$,那就应该是什么$O(n^2)$的做法了。显然这个东西只能是个DP,考虑到题中给出的是一个树形结构,那么就可以利用子树的相对独立性进行DP:设$f_{i,j}$表示以$i$为根的子树中有$j$个点的权值大于$i$的权值时的方案数,显然最终答案就是$\sum_{i}f_{root,i}$。

然后考虑怎么求出答案。通常树形DP都是自底向上逐个合并来得到每个点的DP值的,但注意这个DP无法做到像普通的树形DP一样可以快速(比如$O(1)$或者$O(\log^2 n)$之类)合并。不过这个DP还是可以比较高效地合并的,设要合并的两个子树大小分别为$n,m$,那么我们就可以通过枚举每一对$(i,j)$对应的$f_{\dots,i}$和$f_{\dots,j}$对合并后的DP数组的贡献来在$O(nm)$的时间内得到它们合并后的DP数组。

具体的合并过程就不写了,大体思路是先枚举最后$i$的权值在整个子树中的排名,然后枚举另一棵子树中有几个点权值比$i$的权值小,最后换元得到枚举$(i,j)$的形式。顺便一提,这个DP方程还需要一个前缀和优化才能做到$O(nm)$合并,还有大于和小于两种情况需要分开处理。

 /**************************************************************
Problem: 3167
User: _Angel_
Language: C++
Result: Accepted
Time:3984 ms
Memory:8792 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=,p=;
int C[maxn][maxn];
struct DP{
int f[maxn],n;
void clear(){
memset(f,,sizeof(f));
n=;
f[]=;
}
DP &operator+=(const DP &b){
static int g[maxn];
memset(g,,sizeof(g));
for(int i=;i<n;i++)for(int j=,tmp=;j<=b.n;j++){
tmp=(tmp+b.f[j-])%p;
g[i+j]=(g[i+j]+(long long)f[i]*tmp%p*C[i+j][j]%p*C[n+b.n-i-j-][b.n-j]%p)%p;
}
memcpy(f,g,sizeof(f));
n+=b.n;
return *this;
}
DP &operator*=(const DP &b){
static int g[maxn];
memset(g,,sizeof(g));
int sum=;
for(int j=;j<b.n;j++)sum=(sum+b.f[j])%p;
for(int i=;i<n;i++)for(int j=,tmp=sum;j<b.n;j++){
g[i+j]=(g[i+j]+(long long)f[i]*tmp%p*C[i+j][j]%p*C[n+b.n-i-j-][b.n-j]%p)%p;
tmp=(tmp-b.f[j]+p)%p;
}
memcpy(f,g,sizeof(f));
n+=b.n;
return *this;
}
}f[maxn];
void dfs(int);
vector<int>G[maxn];
vector<bool>W[maxn];
int T,n,prt[maxn];
int main(){
C[][]=;
for(int i=;i<=;i++)for(int j=;j<=i;j++){
C[i][j]=C[i-][j];
if(j)C[i][j]=(C[i][j]+C[i-][j-])%p;
}
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(prt,,sizeof(prt));
for(int i=;i<=n;i++){
G[i].clear();
W[i].clear();
f[i].clear();
}
for(int i=,x,y;i<n;i++){
char c;
scanf("%d %c%d",&x,&c,&y);
x++;
y++;
G[x].push_back(y);
W[x].push_back(c=='>');
G[y].push_back(x);
W[y].push_back(c=='<');
}
dfs();
int ans=;
for(int i=;i<n;i++)ans=(ans+f[].f[i])%p;
printf("%d\n",ans);
}
return ;
}
void dfs(int x){
for(int i=;i<(int)G[x].size();i++)if(G[x][i]!=prt[x]){
prt[G[x][i]]=x;
dfs(G[x][i]);
if(W[x][i])f[x]+=f[G[x][i]];
else f[x]*=f[G[x][i]];
}
}

bzoj3167 [Heoi2013]Sao的更多相关文章

  1. [BZOJ3167][HEOI2013]SAO[树dp+组合数学]

    题意 给定 \(n\) 个节点和 \(n-1\) 个限制,每个节点有一个权值,每个限制形如:\(a_i< a_j\) ,问有多少个 \(1\) 到 \(n\) 排列满足要求. \(n\leq 1 ...

  2. 【BZOJ3167】[HEOI2013]SAO(动态规划)

    [BZOJ3167][HEOI2013]SAO(动态规划) 题面 BZOJ 洛谷 题解 显然限制条件是一个\(DAG\)(不考虑边的方向的话就是一棵树了). 那么考虑树型\(dp\),设\(f[i][ ...

  3. 【BZOJ3167/4824】[Heoi2013]Sao/[Cqoi2017]老C的键盘

    [BZOJ3167][Heoi2013]Sao Description WelcometoSAO(StrangeandAbnormalOnline).这是一个VRMMORPG,含有n个关卡.但是,挑战 ...

  4. 3167: [Heoi2013]Sao [树形DP]

    3167: [Heoi2013]Sao 题意: n个点的"有向"树,求拓扑排序方案数 Welcome to Sword Art Online!!! 一开始想错了...没有考虑一个点 ...

  5. P4099 [HEOI2013]SAO

    P4099 [HEOI2013]SAO 贼板子有意思的一个题---我()竟然没看题解 有一张连成树的有向图,球拓扑序数量. 树形dp,设\(f[i][j]\)表示\(i\)在子树中\(i\)拓扑序上排 ...

  6. BZOJ 3167: [Heoi2013]Sao

    3167: [Heoi2013]Sao Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 96  Solved: 36[Submit][Status][D ...

  7. P4099 [HEOI2013]SAO(树形dp)

    P4099 [HEOI2013]SAO 我们设$f[u][k]$表示以拓扑序编号为$k$的点$u$,以$u$为根的子树中的元素所组成的序列方案数 蓝后我们在找一个以$v$为根的子树. 我们的任务就是在 ...

  8. [HEOI2013]SAO(树上dp,计数)

    [HEOI2013]SAO (这写了一个晚上QAQ,可能是我太蠢了吧.) 题目说只有\(n-1\)条边,然而每个点又相互联系.说明它的结构是一个类似树的结构,但是是有向边连接的,题目问的是方案个数,那 ...

  9. 【做题记录】 [HEOI2013]SAO

    P4099 [HEOI2013]SAO 类型:树形 \(\text{DP}\) 这里主要补充一下 \(O(n^3)\) 的 \(\text{DP}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博 ...

随机推荐

  1. vue项目在IE下报 [vuex] vuex requires a Promise polyfill in this browser问题

    如下图所示,项目在IE11下打开报错: 因为使用了 ES6 中用来传递异步消息的的Promise,而IE浏览器都不支持. 解决方法: 第一步: 安装 babel-polyfill . babel-po ...

  2. 【xsy1097】 拼图 构造题

    题目大意:请你使用n个图形拼成一个矩形.要求:①这每个图形都由1×1的小正方形组成,而且第i个图形由i个小正方形组成.②除了第1个和第2个图形以外,任意一个图形的所有小正方形,不都在一条直线上. 数据 ...

  3. 【数组】Search for a Range

    题目: Given a sorted array of integers, find the starting and ending position of a given target value. ...

  4. sqldeveloper的安装及其使用教程

    1.安装 下载地址:http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index-098778.htm ...

  5. vue2.0实现底部导航切换效果

    使用vue2.0写移动端的时候,经常会写底部导航效果,点击切换路由效果,实现图片和文字颜色切换.vue2.0也提供了很多ul框架供我们实现效果,今天就用原生的实现一个底部导航切换,直接上代码: 效果图 ...

  6. django项目的生产环境部署,利用nginx+uwsgi

    1.坏境准备 centos6.5 django项目 python坏境(python3.6,) 所需的各种模块(django,uwsgi,sqlite3)具体看坏境 我的测试django项目的数据库用的 ...

  7. 前端通信:ajax设计方案(一)---集成核心请求

    报告,我要说话!xp被历史淘汰了,IE6 say goodbye了,太TM开心了,从此不要兼容IE6了,哈哈哈哈哈哈 报告,我要说话!IE这sb为啥不早点被杀掉呢,找工作听说要兼容IE,立马软了,唉唉 ...

  8. Eclipse svn 中文转成英文

  9. golang基础--func函数

    函数function Go函数不支持 嵌套, 重载和默认参数 支持以下特性: 无须声明原型,不定长度长度变参,多返回值,命名返回值参数,匿名函数,闭包 定义函数使用关键字func,且左侧大括号不能另起 ...

  10. 在PHP中使用MySQL Mysqli操作数据库 ,以及类操作方法

    先来操作函数部分,普遍的MySQL 函数方法,但随着PHP5的发展,有些函数使用的要求加重了,有些则将废弃不用,有些则参数必填... ================================= ...