题目大意:有一颗有$m$个叶子节点的二叉树。

对于叶子节点$i$,$x[i]=(a[i]\ xor\ V_{p[i]})or(b[i]\ xor\ V_{q[i]})$

对于非叶子节点$i$,$x[i]=x[sonl]\ and\ x[sonr]$。

上文的$or$和$xor$均为逻辑运算符。且V为一个长度为$n$的布尔数组,需要你自己构造。

下面问:对于每个非叶子节点$i$,问是否存在一个序列V,使得$x[i]=true$。

数据范围:$n,m≤2\times 10^{5}$

我们先来考虑下暴力应该怎么做

我们直接暴力将以$i$为根的子树内所有叶节点取出,转换出对应的了逻辑表达式,然后根据2-sat那一套建图,直接tarjan即可。

这么搞,数据优秀的话(给你一个毛毛虫图),你就会爆炸

考虑一种不会爆炸的做法:

我们对这棵树跑一次树剖,我们根据链长依次在链上进行二分,查找出最接近根的,能够构造出true的点。

然后冷静分析一波,发现这个复杂度好像是$O(n\log^2\ n)$的,似乎问题不大。

可是问题在于这一题采用$O(n^2)$的做法可以直接艹过此题,我就并没有去写高级做法了qwq

 #include<bits/stdc++.h>
#define M 500005
using namespace std; int n,m,rt=;
int p[M]={},q[M]={},A[M]={},B[M]={},in[M]={}; vector<int> G[M]; void ReadData(){
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
int P,Q; scanf("%d%d",&P,&Q);
p[i]=abs(P); q[i]=abs(Q);
A[i]=(P<); B[i]=(Q<);
}
for(int i=m+;i<m*;i++){
int x,y; scanf("%d%d",&x,&y);
G[i].push_back(x);
G[i].push_back(y);
in[x]++; in[y]++;
}
for(int i=;i<m*;i++)
if(in[i]==){rt=i;}
} struct edge{int u,next;}e[M*]={}; int head[M]={},use=;
void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;}
int dfn[M]={},low[M]={},b[M]={},d[M]={},cnt=,t=; stack<int> s;
void dfs(int x){
dfn[x]=low[x]=++t; b[x]=; s.push(x);
for(int i=head[x];i;i=e[i].next)
if(!dfn[e[i].u]) dfs(e[i].u),low[x]=min(low[x],low[e[i].u]);
else if(b[e[i].u]) low[x]=min(low[x],dfn[e[i].u]);
if(dfn[x]==low[x]){
cnt++; int u;
do{
u=s.top(); s.pop();
b[u]=; d[u]=cnt;
}while(u!=x);
}
} vector<int> List;
void findpoint(int x){
int X;
X=p[x]; dfn[X]=d[X]=head[X]=;
X+=n; dfn[X]=d[X]=head[X]=;
X=q[x]; dfn[X]=d[X]=head[X]=;
X+=n; dfn[X]=d[X]=head[X]=;
if(G[x].size()==){
List.push_back(x);
return;
}
for(int i=;i<G[x].size();i++)
findpoint(G[x][i]);
} bool check(int x){
List.clear();
use=cnt=t=;
findpoint(x);
for(int i=;i<List.size();i++){
int v = List[i];
int rtid = q[v], lftid = p[v];
int lft = A[v], rt = B[v];
add(rtid+rt*n,lftid+(-lft)*n);
add(lftid+lft*n,rtid+(-rt)*n);
}
for(int i=;i<List.size();i++){
int now=List[i];
int u=p[now],v=q[now];
if(!dfn[u]) dfs(u);
if(!dfn[v]) dfs(v);
}
for(int i=;i<List.size();i++){
int now=List[i];
int u=p[now],v=q[now];
if(d[u]==d[u+n]) return ;
if(d[v]==d[v+n]) return ;
}
return ;
} int ans[M]={};
bool solve(int x,int ok){
if(G[x].size()==) return ;
if(!ok) ok=check(x);
if(ok) ans[x-m]=;
solve(G[x][],ok); solve(G[x][],ok);
} int main(){
ReadData();
solve(rt,);
for(int i=;i<m;i++) printf("%d",ans[i]);
}

【2019北京集训3】逻辑 树剖+2-sat的更多相关文章

  1. 【2019北京集训2】duck 线段树优化建图+tarjan

    题目大意:给你$n$个点,第$i$个点有点权$v_i$.你需要将这$n$个点排成一排,第$i$个点的点权能被累加当且仅当这个点前面存在编号在$[l_i,r_i]$中的点,问你这些点应该如何排列,点权和 ...

  2. 【2019北京集训测试赛(十三)】数据(sj) 冷静分析

    题目大意:给你一个代表区间$[1,n]$的线段树,问你随机访问区间$[1,n]$中的一个子区间,覆盖到的线段树节点个数的期望(需要乘上$\frac{n(n-1)}{2}$后输出). 数据范围:$n≤1 ...

  3. 【2019北京集训2】Elephant 平衡树

    题目大意:给你一个长度为$n$的序列$A_i$,有$q$次操作,每次操作为以下三种之一: 询问区间的$F_M(A_i)$的最大公约数. 区间翻转,区间加一个正数. 我们定义$gcd(0,0)=0$,且 ...

  4. 【2019北京集训测试赛(七)】 操作 分治+FFT+生成函数

    题目大意:你有$n$个操作和一个初始为$0$的变量$x$. 第$i$个操作为:以$P_i$的概率给$x$加上$A_i$,剩下$1-P_i$的概率给$x$乘上$B_i$. 你袭击生成了一个长度为$n$的 ...

  5. 【2019北京集训六】路径(path) 二分+DP

    此题niubi! 题目大意:给你一颗n个点的点带权无根树,现在请您进行以下两步操作: 1,选择一个$[0,T]$之间的整数$C$,并令所有的点权$wi$变为$(wi+C)%MOD$ 2,选择若干条点不 ...

  6. 2019.01.19 codeforces343D.Water Tree(树剖+ODT)

    传送门 ODTODTODT板子题. 支持子树01覆盖,路径01覆盖,询问一个点的值. 思路:当然可以用树剖+线段树,不过树剖+ODTODTODT也可以很好的水过去. 注意修改路径时每次跳重链都要修改. ...

  7. [2016北京集训试题7]thr-[树形dp+树链剖分+启发式合并]

    Description Solution 神仙操作orz. 首先看数据范围,显然不可能是O(n2)的.(即绝对不是枚举那么简单的),我们考虑dp. 定义f(x,k)为以x为根的子树中与x距离为k的节点 ...

  8. 2016北京集训测试赛(十一)Problem C: 树链问题

    Solution 智障暴力题, 每个点维护一下子树信息, 树剖就好了. 我居然还傻了写了一发毛毛虫... #include <cstdio> #include <cctype> ...

  9. 2019牛客暑期多校训练营(第六场)C:Palindrome Mouse(回文树+树剖)

    题意:给定字符串Str,求出回文串集合为S,问S中的(a,b)满足a是b的子串的对数. 思路:开始和题解的思路差不多,维护当前后缀的每个串的最后出现位置,但是不知道怎么套“最小回文分割”,所以想到了树 ...

随机推荐

  1. Linux shell 信号继承

    shell中,向进程发送信号多多通过ctrl键加上一些功能键来实现,这里是常见的Ctrl组合键及其意义: 组合键 信号类型 意义 Ctrl+C INT信号,即interrupt信号 停止运行当前的作业 ...

  2. datatables插件提示Cannot reinitialise DataTable的解决办法

    这个错误是由于重新设置数据源,又没有将原来的数据清空导致的. 网上有很多解决方案,试了都不管用. 最后找到一种方法,将原来的table销毁,再初始化. 方法是在datatable初始化的时候加入属性 ...

  3. 【VBA】セールの値は配列に変換方法

    方法一 Sub test1() //変数の定義 Dim a() As Integer, iRow As Long, i As Integer //非空白のセールまでの行を取得 iRow = Cells ...

  4. 求树的直径+并查集(bfs,dfs都可以)hdu4514

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...

  5. 149. Max Points on a Line同一条线上的最多点数

    [抄题]: Given n points on a 2D plane, find the maximum number of points that lie on the same straight ...

  6. Head First Servlets & JSP 学习笔记 第十一章 —— Web应用部署

    jar:java archive(java归档) war:web archive(web归档) war文件只是Web应用结构的一个快照,采用了一种更可移植的压缩形式(它实际上就是一个jar文件).建立 ...

  7. Mybatis配置问题解决Invalid bound statement (not found)

    首先这个异常的原因是系统根据Mapper类的方法名找不到对应的映射文件. 网上也搜索了到了类似的文章,一般可以从以下几个点排查: mapper.xml的namespace要写所映射接口的全称类名,而且 ...

  8. Python开发——数据类型【字符串格式化】

    字符串格式化之——% # 字符串格式化 msg = 'I am %s , My hobby is %s'%('yuan','play') print(msg) # I am yuan , My hob ...

  9. mybatis进阶--一对多查询

    首先,我们还是先给出一个需求:根据订单id查询订单明细——我们知道,一个订单里面可以有多个订单的明细(需求不明确的同学,请留言或者去淘宝网上的订单处点一下就知道了).这个时候,一个订单,对应多个订单的 ...

  10. Java内存泄露监控工具:JVM监控工具介绍

    本文将对JVM监控工具jstack, jconsole, jinfo, jmap, jdb, jstat进行详细的介绍,具体内容请看下文 Sun JDK监控和故障处理工具 名称 主要作用 jps JV ...