【BZOJ-3681】Arietta 网络流 + 线段树合并
3681: Arietta
Time Limit: 20 Sec Memory Limit: 64 MB
Submit: 182 Solved: 70
[Submit][Status][Discuss]
Description
Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中。
但是她从未停止过和恋人 Velding 的书信往来。一天,她准备去探访他。
对着窗外的阳光,临行前她再次弹起了琴。
她的琴的发声十分特殊。
让我们给一个形式化的定义吧。
所有的 n 个音符形成一棵由音符 C ( 1 号节点) 构成的有根树,每一个音符有一个音高 Hi 。
Arietta 有 m 个力度,第 i 个力度能弹出 Di 节点的子树中,音高在 [Li,Ri] 中的任意一个音符。
为了乐曲的和谐,Arietta 最多会弹奏第 i 个力度 Ti 次。
Arietta 想知道她最多能弹出多少个音符。
Input
输入共 m + 3 行。
第一行两个整数 n, m ,意义如题目所述。
第二行 n - 1 个整数 Pi ,表示节点 i ( i = 2 . . . n ) 的父亲节点的编号。
第三行 n 个整数 Hi 。
接下来的 m 行,每行四个整数 Li,Ri,D,Ti
Output
输出一个整数表示 Arietta 最多能弹奏多少音符。
数据范围与约定
对于 100% 的数据,1 ≤ n, m ≤ 10000 。
对于所有数据,1 ≤ Hi , Ti , Pi ≤ n, 1 ≤ Li ≤ Ri ≤ n 。
Sample Input
1 1 2 2
5 3 2 4 1
1 3 2 1
3 5 1 4
Sample Output
HINT
第一个力度弹奏音符5,第二个力度弹奏音符1,2,4。
数据范围与约定
对于 100% 的数据,1 ≤ n, m ≤ 10000 。
对于所有数据1<=Hi,Ti,Pi<=N,1<=Li<=Ri<=N
Source
Solution
怎么看都和A+B problem很类似,所以肯定是 主席树优化构图 + 网络流
这样的树形态主席树,用线段树合并会很方便得到每个子树对应的主席树形态,注意一下细节就好了,数组大小得斟酌着开!!!..
这样的话,点数大概是$O(2NlogN+M)$级,边数大概在$O(2NlogN+MlogL)$级。
但是这题内存64M还是有点小卡的..一开始没有判断lson和rson是否存在就直接连边了,造成连了大量无用的边,MLE了一次,在连边的时候注意一下是否有意义即可。
不知道程序里好像有什么奇怪的地方..本机拍一组大样例RE..因为连边时有某个点编号连完后变大了10倍..其余的应该是没什么问题..谁知道这沙茶程序出了啥毛病(捂脸
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
} #define MAXN 400010
#define INF 0x7fffffff int N,M,sz=1; struct EdgeNode{
int next,to,cap;
}edge[1000010];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
inline void InsertEdge(int u,int v,int w) {/*printf("<%d,%d>%d\n",u,v,w);*/ AddEdge(u,v,w); AddEdge(v,u,0);} int h[MAXN],cur[MAXN],S,T;
queue<int>q;
inline bool Bfs()
{
for (int i=0; i<=sz; i++) h[i]=-1;
q.push(S); h[S]=0;
while (!q.empty()) {
int now=q.front(); q.pop();
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && h[edge[i].to]==-1)
h[edge[i].to]=h[now]+1,q.push(edge[i].to);
}
return h[T]!=-1;
} inline int Dfs(int now,int low)
{
if (now==T) return low;
int w,used=0;
for (int i=cur[now]; i; i=edge[i].next)
if (edge[i].cap && h[edge[i].to]==h[now]+1) {
int w=Dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^1].cap+=w; used+=w;
if (used==low) return used;
if (edge[i].cap) cur[now]=i;
}
if (!used) h[now]=-1;
return used;
} inline int Dinic()
{
int re=0;
while (Bfs()) {
for (int i=0; i<=sz; i++) cur[i]=head[i];
re+=Dfs(S,INF);
}
return re;
} struct SgtNode{
int lson,rson;
}tree[10010*80]; int root[MAXN];
inline void Insert(int &x,int l,int r,int pos)
{
x=++sz;
if (l==r) {
InsertEdge(x,T,1);
return;
}
int mid=(l+r)>>1;
if (pos<=mid) Insert(tree[x].lson,l,mid,pos),InsertEdge(x,tree[x].lson,INF);
else Insert(tree[x].rson,mid+1,r,pos),InsertEdge(x,tree[x].rson,INF);
} inline int Merge(int x,int y,int l,int r)
{
if (!x || !y) return x|y;
int z=++sz;
if (l==r) {
InsertEdge(z,x,INF),InsertEdge(z,y,INF);
return z;
}
int mid=(l+r)>>1;
tree[z].lson=Merge(tree[x].lson,tree[y].lson,l,mid);
if (tree[z].lson) InsertEdge(z,tree[z].lson,INF);
tree[z].rson=Merge(tree[x].rson,tree[y].rson,mid+1,r);
if (tree[z].rson) InsertEdge(z,tree[z].rson,INF);
return z;
} inline void Query(int x,int l,int r,int L,int R,int id)
{
if (!x) return;
if (L<=l && R>=r) {
InsertEdge(id,x,INF);
return;
}
int mid=(l+r)>>1;
if (L<=mid) Query(tree[x].lson,l,mid,L,R,id);
if (R>mid) Query(tree[x].rson,mid+1,r,L,R,id);
} vector<int>son[MAXN];
inline void DFS(int now)
{
for (int i=0; i<son[now].size(); i++) {
DFS(son[now][i]);
root[now]=Merge(root[now],root[son[now][i]],1,N);
}
} int main()
{ N=read(),M=read(); for (int i=2,x; i<=N; i++) x=read(),son[x].push_back(i); S=0,T=1; for (int i=1,x; i<=N; i++) x=read(),Insert(root[i],1,N,x); DFS(1); for (int i=1; i<=M; i++) {
int L=read(),R=read(),D=read(),Ti=read();
InsertEdge(S,++sz,Ti); Query(root[D],1,N,L,R,sz);
} printf("%d\n",Dinic()); return 0;
}
【BZOJ-3681】Arietta 网络流 + 线段树合并的更多相关文章
- BZOJ.3545.[ONTAK2010]Peaks(线段树合并)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...
- bzoj 4631: 踩气球 线段树合并
4631: 踩气球 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 265 Solved: 136[Submit][Status][Discuss] ...
- BZOJ:5457: 城市(线段树合并)(尚待优化)
5457: 城市 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 18 Solved: 12[Submit][Status][Discuss] Des ...
- bzoj 4756 Promotion Counting —— 线段树合并
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4756 合并子树的权值线段树: merge 返回 int 或者是 void 都可以. 代码如下 ...
- [BZOJ3681]Arietta(可持久化线段树合并优化建图+网络流)
暴力建图显然就是S->i连1,i->j'连inf(i为第j个力度能弹出的音符),j'->T连T[j]. 由于是“某棵子树中权值在某区间内的所有点”都向某个力度连边,于是线段树优化建图 ...
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...
- BZOJ.4399.魔法少女LJJ(线段树合并)
BZOJ 注意\(c\leq7\)→_→ 然后就是裸的权值线段树+线段树合并了. 对于取\(\max/\min\)操作可以直接区间修改清空超出范围的值,然后更新到对应位置上就行了(比如对\(v\)取\ ...
- BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)
BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...
- BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...
随机推荐
- 何凯文每日一句打卡||DAY7
- Excel VBA保护工作表
'设定可编辑区域 ActiveSheet.Protection.AllowEditRanges.Add Title:="区域1", Range:=Range("E5:H1 ...
- [整理]HTML5 WebSocket
vs2013 win7 iis7.5貌似不行,查阅了资料,好像得iis8支持 <ASP.NET SignalR系列>第一课 认识SignalR http://www.cnblogs.com ...
- 【问题收集·知识储备】Xcode只能选择My Mac,不能选择模拟器如何解决?
网友问题:请问打开一个应用,只能选择My Mac,不能选择模拟器如何解决? 答案: 下面将问答过程记录如下: CHENYILONG Blog 请问打开一个应用,只能 ...
- 第12月第26天 swift 下划线
1. The _ is used to define that the parameter is not named If you have multiple _ it states that you ...
- 【ORACLE】创建表空间
CREATE TABLESPACE dna36 DATAFILE 'D:\oracle\oradata\orcl\dna36.dbf' SIZE 100M AUTOEXTEND ON NEXT 10M ...
- linux笔记_day10_shell编程
1.shell编程 编程语言 静态语言:编译型语言 强类型(变量在使用前,必须事先声明) 事先转换成可执行语言 动态语言:解释型语言 弱类型(变量用时声明,拿来直接用,甚至不区分数据类型,一般默认都为 ...
- Flask源码解析:Flask应用执行流程及原理
WSGI WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述服务器端如何与web应用程序通信的 ...
- 使用badblocks命令检测、修复硬盘坏道(待验证)
今天我的新硬盘到了.暂时没想好怎么用它.可以把它装入光驱位硬盘架给G430用,也可以把它当成移动硬盘来用. 想起以前记录过一个badblocks的用法,用来检查坏道,这里再贴一遍备用. ####### ...
- python 列表元组加减乘除法
元组(typle)列表(list)没有减法和除法,但有加法和乘法. 1.加法,即把元素相加.只可以list和tuple相加,不能加其他类型. t= (1, ) + (2, 3, 4) print(t, ...