bzoj 3681 Arietta
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 5 2 1 1 2 2 5 3 2 4 1 1 3 2 1 3 5 1 4 Sample Output 4 HINT
第一个力度弹奏音符5,第二个力度弹奏音符1,2,4。
数据范围与约定
对于 100% 的数据,1 ≤ n, m ≤ 10000 。
对于所有数据1<=Hi,Ti,Pi<=N,1<=Li<=Ri<=N
Source
Shinrein祭 #1
考虑可以怎么做 题目相当于每次向一棵子树内的所有权值在一个区间范围内的点连边 然后每个点出边的最大容量为1 那么跑最大流即可 但是因为复杂度是n*m的显然是不可以接受的那么不妨考虑优化建图 那么就在每个节点维护以权值为下标的线段树 有个显然的做法就是像par树一样从底向上合并上来但这题不可以 因为一个权值可能多个出边 并且这样似乎复杂度不对?
那么就考虑主席树的做法 首先针对原树进行轻重链的划分 然后每个节点直接从子树重儿子继承过来 然后其他轻儿子就用启发式合并即可 可以证明这个复杂度是log^2的 即 点数 n*log(n)^2+n+m 边数 2*n*log(n)^2+m*log(n)
#include#include#include#include#include#includeusing namespace std;inline char gc(){ static char now[1<<16],*S,*T; if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;} return *S++;}inline int read(){ int x=0,f=1;char ch=gc(); while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();} while(isdigit(ch)) x=x*10+ch-'0',ch=gc(); return x*f;}const int N=1e4+10;const int NN=1300010;const int inf=0x3f3f3f3f;struct node{ int y,next,z;}data[NN<<1];struct node1{ int left,right;}tree[NN];int num=1,rt[N],H[N],h[NN],size[N],cnt,level[NN],T,n,m,cur[NN];vectorson[N];inline void insert2(int x,int y,int z){ data[++num].y=y;data[num].next=h[x];data[num].z=z;h[x]=num; data[++num].y=x;data[num].next=h[y];data[num].z=0;h[y]=num;}inline bool bfs(){ queueq;q.push(0);memset(level,0,sizeof(level));level[0]=1; while(!q.empty()){ int x=q.front();q.pop(); for (int i=h[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z; if (level[y]||!z) continue;level[y]=level[x]+1;if (y==T) return 1;q.push(y); } }return 0;}inline int dfs(int x,int s){ if (x==T) return s;int ss=s; for (int &i=cur[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z; if (level[x]+1==level[y]&&z){ int xx=dfs(y,min(z,s));if (!xx) level[y]=0; s-=xx;data[i].z-=xx;data[i^1].z+=xx;if (!s) return ss; } }return ss-s;}inline void insert1(int &x,int l,int r,int p,int id){ tree[++cnt]=tree[x];if (x)insert2(cnt+n,x+n,inf);x=cnt; if(l==r) {insert2(x+n,id,inf);return;}int mid=l+r>>1; if (p<=mid) insert1(tree[x].left,l,mid,p,id),insert2(x+n,tree[x].left+n,inf); if (p>mid) insert1(tree[x].right,mid+1,r,p,id),insert2(x+n,tree[x].right+n,inf);}inline void dfs1(int x,int id){ insert1(rt[id],1,n,H[x],x); for (int i=0;imx) mx=size[y],mxid=y; }rt[x]=rt[mxid];insert1(rt[x],1,n,H[x],x); for (int i=0;i=r){insert2(cnt+n,x+n,inf);return;}int mid=l+r>>1; if (l1<=mid) modify(tree[x].left,l,mid,l1,r1); if (r1>mid) modify(tree[x].right,mid+1,r,l1,r1);}int main(){ freopen("bzoj3681.in","r",stdin); n=read();m=read(); for (int i=2;i<=n;++i) son[read()].push_back(i); for (int i=1;i<=n;++i) H[i]=read();dfs_init(1); for (int i=1;i<=m;++i){ int l=read(),r=read(),d=read(),t=read(); ++cnt;insert2(0,cnt+n,t);modify(rt[d],1,n,l,r); }T=cnt+1+n;int ans=0; for (int i=1;i<=n;++i) insert2(i,T,1); /*for (int i=2;i<=num;++i){ printf("%d %d %d\n",data[i].x,data[i].y,data[i].z); }*/ while(bfs()) memcpy(cur,h,sizeof(h)),ans+=dfs(0,inf); printf("%d\n",ans); return 0;}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~