给n<=100000个点的树,每个点有一个01串,长度m<=200,串的可以随时01取反,串的每一位对应权Vi,从根节点到某个节点经过决定哪些串取反后取得的最大价值为某个点的权值,求:在这棵树上乱走,不能走权相同的相邻两点,每个长度D的简单路径的方案数。

题目很奇怪。结论很不显然。TJM和HR大佬很强。

首先,最后遍历的树的深度不会超过logm。在树上每走一步,都可以把0的个数减少至少一半。

其次,未达到最大值的两个点权值肯定不同。道理同上。因此把目标转化为“在权值未满的树上走”,重点在如何找出这棵树。

再者,Mi表示属性i的选择情况,在n个串中,当且仅当所有的Mi取遍2^n种集合时没有最优方案,最优方案即所有属性都取得到。在这m个选择情况中若取遍2^n种集合,则有全为0的Mi,必须把它某一位对应的串取反,但这意味着那个“只有这一位为0的选择情况”不合法,我们要选另一位,这样一直搞下去,所有的串都取反了,那那些全为1的Mi就gg了。

最后,在n个串中,若Mi没取遍2^n种集合,一定可以构造出最优方案。方法即把不存在的某个选择情况的1的位取反。这时除非某个选择情况与不存在的那种完全相同,否则必然会有一位为1。

于是,两次dfs解决。第二次dfs的统计方案易错,注意一下。

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
//#include<iostream>
using namespace std; int n,m;
#define maxn 100011
char s[];bool mp[maxn][];
struct Edge{int to,next;};
int vis[],state[];
#define LL long long
LL dis[][],ans[];
struct Tree
{
Edge edge[maxn<<];
int first[maxn],le;
Tree() {le=;}
void in(int x,int y)
{
edge[le].to=y;
edge[le].next=first[x];
first[x]=le++;
}
void dfsfirst(int x,int dep)
{
int tot=(<<dep);
for (int i=;i<=m;i++)
{
if (mp[x][i]) state[i]|=<<(dep-);
if (vis[state[i]]!=x) tot--,vis[state[i]]=x;
}
if (tot) first[x]=;
for (int i=first[x];i;i=edge[i].next)
dfsfirst(edge[i].to,dep+);
for (int i=;i<=m;i++)
if (mp[x][i]) state[i]^=<<(dep-);
}
void dfsfirst()
{
memset(vis,,sizeof(vis));
dfsfirst(,);
}
void dfssec(int x,int dep)
{
memset(dis[dep],,sizeof(dis[dep]));
dis[dep][]=dis[dep][]=;
for (int i=first[x];i;i=edge[i].next)
{
dfssec(edge[i].to,dep+);
for (int j=dep+;j<=;j++)
for (int k=dep+;k<=;k++)
ans[j+k-dep-dep]+=dis[dep][j-dep]*dis[dep+][k-dep];
for (int j=;j<=-dep-dep;j++) dis[dep][j+]+=dis[dep+][j];
}
}
void dfssec() {dfssec(,);}
}t;
int x;
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
scanf("%s",s);
for (int j=;j<m;j++) mp[i][j+]=s[j]-'';
}
for (int i=;i<=m;i++) scanf("%d",&x);
for (int i=;i<=n;i++) scanf("%d",&x),t.in(x,i);
t.dfsfirst();
memset(ans,,sizeof(ans));
t.dfssec();
int i;
for (i=;i>=;i--) if (ans[i]) break;
printf("%d ",n);
for (int j=;j<=i;j++) printf("%lld ",ans[j]);
return ;
}

汕头市赛srm1X T3的更多相关文章

  1. 汕头市队赛SRM14 T3覆盖

    我们可以考虑两种情况 区间之间不相重叠 和 重叠 f[i][j]表示以当前最后一个区间以 i 结尾 并且选了 j 个区间 不相重叠的话 只要选 1-i-w 的max再加上 包含i在内的前四个数的和 相 ...

  2. 汕头市队赛 SRM13 T3

    这道题可以贪心 维护一个答案队列 枚举位置 每次将比当前位置大的队尾全部替代掉 记录删了多少了就好了 #include<cstdio> #include<iostream> # ...

  3. 汕头市队赛 SRM1X T2 ——扫描线

    绵津见-终 SRM 13 背景 “西瓜也是可以种在海上的!”——绵津见 然而种在海上的西瓜最需要防范的,是时不时会涌向瓜田的阵阵海浪. 幸好,身为海神的绵津见可以释放魔法“水平如镜”来阻止海浪拍打西瓜 ...

  4. 汕头市队赛 SRM1X T1

    木之本樱 背景 “西瓜是可以种在树上的!”——木之本樱 描述 空地上,一排排的西瓜树拔地而起. 魔法世界里,空地是无限大的.所有的树排成了n条直线,每条直线也是向左右两端无限延伸的. 由于自己姓木(之 ...

  5. 汕头市队赛 SRM10 T3 数学上来先打表

    数学上来先打表 SRM 10 描述 给出 n个点(不同点之间有区别),求出满足下列条件的连边(双向边)方案:1.每条边连接两个不同的点,每两个点之间至多有一条边2.不存在三个点a,b,c使三个点间两两 ...

  6. 洛谷noip 模拟赛 day1 T3

    T7983 大芳的逆行板载 题目背景 大芳有一个不太好的习惯:在车里养青蛙.青蛙在一个n厘米(11n毫米s)的Van♂杆子上跳来跳去.她时常盯着青蛙看,以至于突然逆行不得不开始躲交叉弹.有一天他突发奇 ...

  7. 「2018-12-02模拟赛」T3 约束排列 解题报告

    3.约束排列(place.pas/cpp/in/out) 问题描述: 给出 n 个互不相同的小写字母,表示出现的字符类型,以及 k 个约束关系: .....,表示 ai 必须出现在 bi 前面(ai, ...

  8. 雅礼 noip2018 模拟赛 day3 T3

    典型树形dp 这里,我们应该看到一些基本性质: ①:如果这个边不能改(不是没有必要改),我们就不改,因为就算改过去还要改回来,显然不是最优的 注意:"不能改"是指边的性质和要求的相 ...

  9. war2 洛谷模拟赛day2 t3 状压

    (new )   war2 题解:总体数据而言,我们很容易想到着就是DP啊,我们DP数组,用状态压缩,代表有那些点已经被占领过了,代表上一次我占的是那个.对于每一次状态转移,若当前我们要占领的Port ...

随机推荐

  1. 9.JAVA-抽象类定义

    1.抽象类 抽象类,用来表示一个抽象概念. 是一种只能定义类型,而不能产生对象的类,所以定义了抽象类则必须有子类的出现. 抽象类的好处在于能够明确地定义子类需要覆写的方法 抽象类需要使用abstrac ...

  2. linux小白成长之路12————​Docker部署Nginx

    [内容指引] Docker安装Nginx: 简单启动: 准备配置文件: 一.Docker安装Nginx 指令:docker pull nginx 二.简单启动 指令:docker run --name ...

  3. java访问数据库步骤详解

    eg1: public static void main(String[] args) throws ClassNotFoundException, SQLException { //第一步:加载JD ...

  4. win7系统 windows update 总是更新失败解决方法:

    win7系统 windows update 总是更新失败解决方法: 右键单击桌面“计算机”选择“管理“. 进到“计算机管理“窗口后,展开”服务和应用程序“并双击”服务“,在窗口右侧按照名称找到”Win ...

  5. 利用CWinThread实现跨线程父子MFC窗口

    利用CWinThread实现跨线程父子MFC窗口 MFC对象只能由创建该对象的线程访问,而不能由其他线程访问. 不遵守该准则将导致断言(assertion)或者无法预知的程序行为等运行期错误. 在多线 ...

  6. pytorch系列 -- 9 pytorch nn.init 中实现的初始化函数 uniform, normal, const, Xavier, He initialization

    本文内容:1. Xavier 初始化2. nn.init 中各种初始化函数3. He 初始化 torch.init https://pytorch.org/docs/stable/nn.html#to ...

  7. ios之数据持久化

    9.1 数据持久化概述 iOS中可以有四种持久化数据的方式: 属性列表.对象归档.SQLite3和Core Data 9.2 iOS应用程序目录结构 iOS应用程序运行在Mac os模拟器时候,有一下 ...

  8. 牛客OI赛制测试赛2 C 数组下标

    链接:https://www.nowcoder.com/acm/contest/185/C来源:牛客网 题目描述 给出一个数列 A,求出一个数列B. 其中Bi   表示 数列A中 Ai 右边第一个比 ...

  9. 连接远程docker内的mysql(navicat)

    拉取mysql镜像 docker pull mysql:5.6 查看mysql镜像 docker images | grep mysql 启动mysql容器 docker run -p 3306:33 ...

  10. POJ-3190-分配畜栏

    这个题首先,我们需要注意的是它的时间是一秒,其中还包括了你读入数据的时间,因为cin我写的时候没有解除绑定,所以直接超时,我们直接用scanf函数读入50000组数据好了. 然后就是poj交的时候,如 ...