树形DP

f[i][0]表示不向下连边的最大匹配数

f[i][1]表示向下连一条边的最大匹配数

h[][]表示对应的方案数

为了防止爆栈用BFS

为了防止MLE:

1.数组循环利用,比如存边的数组在存完边后可以用来当dp数组

2.BFS时判断哪些点已经走过的bool数组改成bitset

3.能不开数组就不开数组,如前缀积

4.对于数值不超过n的数组,改成手写的3个unsigned char组合而成的数据类型,可以压缩1/4内存

5.记录方案的数组只要开int,计算时强制转化成long long

压了好久内存,终于从77M压到了31M…我发现bool占用空间居然和char是一样的!结构体占用内存是按照里面最大的那种数据类型为基准计算的。

#include<cstdio>
#include<bitset>
typedef long long ll;
const int N=1500001;
int n,m,i,j,x,y,g[N],v[N<<1],ed,head,tail,maxv,pre,now,t0,t1;
std::bitset<N>in;
struct Num{
unsigned char a,b,c;
Num(){a=b=c=0;}
Num(int x){a=x&255,x>>=8,b=x&255,c=x>>8;}
}nxt[N<<1],q[N];
inline int Real(Num x){return (int)x.a|(int)x.b<<8|(int)x.c<<16;}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add(int x,int y){v[++ed]=y;nxt[ed]=Num(g[x]);g[x]=ed;}
inline ll mul(ll a,ll b){return a*b%m;}
inline void max(int b){if(maxv<b)maxv=b;}
int main(){
read(n);
for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
read(m);
in[Real(q[head=tail=1]=Num(1))]=1;
while(head<=tail)for(i=g[x=Real(q[head++])],g[x]=tail+1;i;i=Real(nxt[i]))if(!in[v[i]])in[Real(q[++tail]=Num(v[i]))]=1;
for(i=1;i<=n*2;i++)nxt[i]=Num(v[i]=0);
for(i=n;i;i--){
v[x=Real(q[i])]=1;
if(g[x]>g[Real(q[i+1])]-1)continue;
maxv=-N;head=g[x];tail=g[Real(q[i+1])]-1;now=0;
for(j=head;j<=tail;j++){
y=Real(q[j]),t0=Real(nxt[y]),t1=Real(nxt[y+n]);
if(t0>t1){
now+=t0;
v[x]=mul(v[x],v[y]);
v[y+n]=v[y];
max(0);
}else if(t0==t1){
now+=t0;
v[x]=mul(v[x],v[y]+v[y+n]);
v[y+n]=(v[y]+v[y+n])%m;
max(0);
}else{
now+=t1;
v[x]=mul(v[x],v[y+n]);
max(t0-t1);
}
g[y]=v[y+n];
}
nxt[x]=Num(now);now+=maxv+1;
nxt[x+n]=Num(now);
pre=g[Real(q[tail+1])]=1;
for(j=tail-1;j>=head;j--)g[Real(q[j])]=mul(g[Real(q[j])],g[Real(q[j+1])]);
for(j=head;j<=tail;j++){
y=Real(q[j]),t0=Real(nxt[y]),t1=Real(nxt[y+n]);
if(t0>=t1){
if(maxv==0)v[x+n]=(v[x+n]+mul(mul(pre,g[Real(q[j+1])]),v[y]))%m;
}else{
if(maxv==t0-t1)v[x+n]=(v[x+n]+mul(mul(pre,g[Real(q[j+1])]),v[y]))%m;
}
pre=mul(pre,v[y+n]);
}
}
if(Real(nxt[1])>Real(nxt[1+n]))printf("%d\n%d",Real(nxt[1]),v[1]%m);
else if(Real(nxt[1])==Real(nxt[1+n]))printf("%d\n%d",Real(nxt[1]),(v[1]+v[1+n])%m);
else printf("%d\n%d",Real(nxt[1+n]),v[1+n]%m);
return 0;
}

  

BZOJ3547 : [ONTAK2010]Matchings的更多相关文章

  1. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  2. [ACM_动态规划] ZOJ 1425 Crossed Matchings(交叉最大匹配 动态规划)

    Description There are two rows of positive integer numbers. We can draw one line segment between any ...

  3. 【BZOJ】【3550】【ONTAK2010】Vacation

    网络流/费用流 Orz太神犇了这题…… 我一开始想成跟Intervals那题一样了……每个数a[i]相当于覆盖了(a[i]-n,a[i]+n)这个区间……但是这样是错的!!随便就找出反例了……我居然还 ...

  4. BZOJ3550: [ONTAK2010]Vacation

    3550: [ONTAK2010]Vacation Time Limit: 10 Sec  Memory Limit: 96 MBSubmit: 91  Solved: 71[Submit][Stat ...

  5. bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Stat ...

  6. POJ 1692 Crossed Matchings(DP)

    Description There are two rows of positive integer numbers. We can draw one line segment between any ...

  7. BZOJ 3544: [ONTAK2010]Creative Accounting( BST )

    题意 : 一段序列 , 求一段子序列和取余 M 的最大值 其实是一道水题... 前缀和 , 然后就是找 ( sum( r ) - sum( l ) ) % M 的最大值 . 考虑一个 sum( r ) ...

  8. BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )

    这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...

  9. BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]

    3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...

随机推荐

  1. ruby实时查看日志

    (文章是从我的个人主页上粘贴过来的, 大家也可以访问我的主页 www.iwangzheng.com) 在调试代码的时候,把日志文件打开,边操作边调试能很快帮助我们发现系统中存在的问题. $tail r ...

  2. hiho #1143 : 骨牌覆盖问题·一 (运用快速幂矩阵)

    #1143 : 骨牌覆盖问题·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题:我们有一个2xN的长条形棋盘,然 ...

  3. Scrapy and Selenium

    How to scrapy js? scrapy结合webkit抓取js生成的页面 http://www.cnblogs.com/Safe3/archive/2011/10/19/2217965.ht ...

  4. spring事物传播属性

    PROPAGATION_REQUIRED Support a current transaction; create a new one if none exists.  支持一个当前事务;如果不存在 ...

  5. velocity的string转数字,numberTool

    velocity的string转数字,非常有意思: 1.通过java的包装类进行转换 #set($intString = "20") #set($Integer = 0) $Int ...

  6. 使用WebDriver遇到的那些坑(转)

    http://www.huangbowen.net/blog/2013/06/25/practice-of-webdriver/ 在做web项目的自动化端到端测试时主要使用的是Selenium Web ...

  7. kettle转换JavaScript获取命令行参数

    日常开发中由于很多参数是变化的,需要在部署时才能确定.而写在配置文件里又显得很笨重,因而可以运行时实时指定.那么kettle是怎么获取命令行中的参数的呢? kettle可以通过转换里的JavaScri ...

  8. kettle转换JavaScript加载外部js文件

    日常开发中,时常会出现这样一种情况.有大量的函数是通用的.而每个JavaScript里面写一遍,给维护带来很大的困扰.因而需要将公共的函数写在外部js文件中.这时就需要引入外部的公共文件了.下面是在转 ...

  9. Android 和iOS 中关于View 的一点知识

    View的概念和方法十分重要,这里将对Android 和iOS中出现的,关于视图的一些知识点进行总结,预计文章会比较长,要许多时间慢慢补充. 先转载一部分资料,感谢原作者! 原链接为:http://b ...

  10. 单个php页面实现301重定向

    301重定向的意思是页面永久性移走,实现方式是当用户请求页面时,服务器返回相应http数据流头信息状态码为301,表示本网页永久性转移到另一个地址,301重定向是页面永久性转移,一般用在不打算改变的地 ...