传送门
思路:
题目来源于Contest Hunter
红太阳mrazer和我说的
第一次做这种数据结构优化网络流的题目之前只是停留在口胡的地步
网上的题解不多,官方题解给出的比较标准的做法是线段树合并+可持久化
不过,蒟蒻表示并没有看懂这种做法,而且好像后来有人发现如果点权相同,64MB的内存根本开不下?
回到题目,建图是显而易见的,关键在如何优化O(nm)O(nm)的边数
暴力的想法是每个节点开一颗权值线段树维护子树内的信息,往区间代表点连边,叶子节点往每个树节点的代表点连边,空间复杂度和时间复杂度都不科学
借助Yveh博客中dsu on tree的思想,我们可以把节点x重儿子的线段树作为节点x的线段树,然后暴力轻儿子所在子树中的信息,这样做可知每个节点的信息最多被暴力统计logn\log n次(也就是其到根路径上重链的数量),空间复杂度O(nlog2n)O(n \log^2 n)
每插入一个点,新建的点要向前一个对应的区间代表点连边,流量inf
说白了就是可持久化权值线段树+启发式合并,应该也是题解中给出的一种做法
连边的时候找对应的权值区间,连边即可,叶子节点也要向外连边
感觉程序有bug,如果有人能hack掉请在下面评论,谢谢
代码:

#include<cstdio>
#include<vector>
#include<iostream>
#include<queue>
#define inf 1e9
#define ls(x) tr[x].ch[0]
#define rs(x) tr[x].ch[1]
#define M 10005
using namespace std;
int in()
{int t=0;char ch=getchar();while (ch>'9'||ch<'0') ch=getchar();while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();return t;
}
int n,m,cnt;
int h[M],siz[M],son[M],root[M];
queue<int>q;
struct node{int l,r,d,t;
}Q[M];
struct tree{int ch[2];
}tr[130*M];
vector<int>e[M];
namespace network
{int s,t,tot=1,first[M*130],cur[M*130],dis[M*130];struct edge{int v,w,next;}e[M*300];void add(int x,int y,int z){e[++tot].v=y;e[tot].w=z;e[tot].next=first[x];first[x]=tot;e[++tot].v=x;e[tot].w=0;e[tot].next=first[y];first[y]=tot;} bool bfs(){for (int i=0;i<=t;++i) dis[i]=0,cur[i]=first[i];int x;dis[s]=1;for (q.push(s);!q.empty();q.pop()){x=q.front();for (int i=first[x];i;i=e[i].next)if (!dis[e[i].v]&&e[i].w)dis[e[i].v]=dis[x]+1,q.push(e[i].v);}return dis[t]>0;}int dfs(int x,int maxn){if (x==t) return maxn;int used=0,k;for (int i=cur[x];i;i=e[i].next)if (dis[e[i].v]==dis[x]+1){k=dfs(e[i].v,min(maxn-used,e[i].w));e[i].w-=k;e[i^1].w+=k;if (e[i].w) cur[x]=i;used+=k;if (used==maxn) return maxn;}if (!used) dis[x]=0;return used;}int dinic(){int ans=0;while (bfs())ans+=dfs(s,inf);return ans;}
}
void build(int rt,int now,int L,int R,int p)
{if (rt) network::add(now,rt,inf);if (L==R) return void(network::add(now,p,1));int mid=(L+R)>>1;if (mid<h[p])ls(now)=ls(rt),rs(now)=++cnt,network::add(now,rs(now),inf),build(rs(rt),rs(now),mid+1,R,p);elsers(now)=rs(rt),ls(now)=++cnt,network::add(now,ls(now),inf),build(ls(rt),ls(now),L,mid,p);
}
void dfs(int x)
{siz[x]=1;for (int v,i=0;i<e[x].size();++i){v=e[x][i];dfs(v);siz[x]+=siz[v];if (siz[son[x]]<siz[v]) son[x]=v;}root[x]=root[son[x]];int tmp=root[x];build(tmp,root[x]=++cnt,1,n,x);for (int v,i=0;i<e[x].size();++i){v=e[x][i];if (v==son[x]) continue;for (q.push(v);!q.empty();q.pop()){v=q.front();tmp=root[x];build(tmp,root[x]=++cnt,1,n,v);for (int j=0;j<e[v].size();++j) q.push(e[v][j]);}}
}
void get(int rt,int L,int R,int id)
{if (Q[id].l<=L&&R<=Q[id].r) return void(network::add(id+n,rt,inf));int mid=L+R>>1;if (mid>=Q[id].l) get(ls(rt),L,mid,id);if (mid<Q[id].r) get(rs(rt),mid+1,R,id);
}
main()
{n=in();m=in();cnt=n+m;for (int i=2;i<=n;++i) e[in()].push_back(i);for (int i=1;i<=n;++i) h[i]=in();for (int i=1;i<=m;++i) Q[i]=(node){in(),in(),in(),in()},network::add(network::s,i+n,Q[i].t);dfs(1);network::s=0;network::t=cnt+1;for (int i=1;i<=m;++i)  get(root[Q[i].d],1,n,i);for (int i=1;i<=n;++i) network::add(i,network::t,1);printf("%d\n",network::dinic());
}

【BZOJ3681】Arietta,主席树优化网络流相关推荐

  1. 【洛谷P3701】 「伪模板」主席树【网络流】

    题目大意: 题目链接:https://www.luogu.org/problemnew/show/P3701 byx和手气君都非常都非常喜欢种树.有一天,他们得到了两颗奇怪的树种,于是各自取了一颗回家 ...

  2. jzoj 4240.【五校联考5day2】游行 主席树优化连边+支配树

    Description 恶梦是学校里面的学生会主席.他今天非常的兴奋,因为学校一年一度的学生节开始啦!! 在这次节日上总共有N个节目,并且总共也有N个舞台供大家表演.其中第i个节目的表演时间为第i个单 ...

  3. P3701 -「伪模板」主席树【网络流,最大流】

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P3701 题目大意 给出若干个人的克制关系 给出两边每个人的种类和血量 ...

  4. P3701 「伪模板」主席树-(网络流最大流)

    题目链接:点击进入 思路 对于每个byx的人,从源点向人连边,容量为此人的寿命. 对于每个诗乃酱的人,从人向汇点连边,容量为此人的寿命. 注:对于主席,他的寿命要多加上sum,sum为本方膜法师的人数 ...

  5. BZOJ 3218 UOJ #77 A+B Problem (主席树、最小割)

    BZOJ 3218 UOJ #77 A+B Problem (主席树.最小割) 大名鼎鼎的A+B Problem, 主席树优化最小割-- 调题死活调不对,一怒之下改了一种写法交上去A了,但是改写法之后 ...

  6. YBTOJ洛谷P2839:最大中位数(主席树、二分答案)

    遇事不决,二分试试 解析 很好的一道题 真是把主席树玩明白了 一个关于中位数的常用trick: 二分答案mid,把>=mid的看成1,<mid的看成-1,然后看最大子段和是否>=0 ...

  7. 主席树 | 莫队 ---- Codeforces Round #716 (Div. 2) D. Cut and Stick [主席树or莫队优化] 区间众数问题(静态)

    题目链接 题目大意: 就是给你nnn个数,和q次询问,每次询问给你一个区间[l,r][l,r][l,r],问你把区间里面的数分配成最少多少块,使得块内出现最多次数的数不超过区间长度的一半(除不尽向上取 ...

  8. zoj - 2112 带修改主席树 + 空间优化

    ZOJ - 2112 题意:求区间第k小 思路:带修改区间第k小裸题,无修改的主席树是维护一个前缀线段树,每次更新log个节点,用root 和 ls rs作为每颗前缀线段树的根节点和左右子树的索引(相 ...

  9. 【CF1045A】A Last chance【贪心】【线段树优化建图】【网络流构造方案】

    题意:有nnn个武器和mmm个飞船,武器有下面三种 从给定的集合SSS中击破一个. 在给定的区间[L,R][L,R][L,R]中击破一个. 对于给定的a,b,ca,b,ca,b,c,选择000个或22 ...

最新文章

  1. Windows10上使用VS2017编译MXNet源码操作步骤(C++)
  2. 【Qt】QTest:编译Qt单元测试程序
  3. (0011) iOS 开发之模拟HTTP请求与响应,返回自己想要的报文。
  4. iOS - Swift NSEnumerator 迭代器
  5. linux PAM模块
  6. 逆向工程核心原理读书笔记-API钩取之隐藏进程(二)
  7. Android之如何ubuntu环境下在手机里面快速找到apk的位置然后拉下来
  8. android nio debug模式正常 release包crash_Flutter包大小治理上的探索与实践
  9. 为什么有些小老板,做了一辈子,还是没办法发展大?
  10. Python中的传值和引用
  11. Java——字符编码详细解释
  12. MFC去掉窗口右上方最大化最小化关闭按钮
  13. 浏览器 - 监听浏览器刷新及关闭
  14. Kylin使用Spark构建Cube
  15. 2004. 职员招聘人数
  16. 网页制作用html和sc,实验二:html的基本标签和javasc
  17. python 对图片进行颜色转换
  18. 什么软件编程是最难的?
  19. 批量识别图片文字并存为Excel,几行Python轻松实现!
  20. 使用LamdbaUpdateWrapper的setSql作用及风险

热门文章

  1. 一个好用的小工具 thefuck
  2. 【Python3网络爬虫开发实战】1.2.1-Requests的安装
  3. Head First设计模式读书笔记六 第七章上 适配器模式
  4. 终端启动service和activity
  5. 韩顺平php视频笔记70 面向对象编程的三大特征1 抽象 封装
  6. python的精髓_教你玩转Python!一文总结Python入门到精髓的窍门
  7. CUDA中并行规约(Parallel Reduction)的优化
  8. mongodb更新操作符$inc,$mul
  9. idea中新建javaWeb项目
  10. python数组类型_一文搞懂Python中的所有数组数据类型