BZOJ3681: Arietta

题解:

数据结构来优化网络流,貌似都是用一段区间来表示一个点,然后各种乱搞。。。

发现主席树好吊。。。在树上建主席树貌似有三种方法:

1.建每个点到根节点这条链上的主席树,可以回答和两点间的路径的XX问题。

2.按DFS序然后就成了序列上的主席树,可以回答子树第k大等XX问题。

3.先给每个点单独建立主席树,然后dfs下去,并且将一个点的所有子树合并起来,相当于新建了n棵主席树,但这样可以解决该题。。。

神犇勿喷。。。

因为这样从rt[x]查询到的区间就可以直接表示满足题意的点了,然后就是最大流了。

代码:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<iostream>
  7 #include<vector>
  8 #include<map>
  9 #include<set>
 10 #include<queue>
 11 #include<string>
 12 #define inf 1000000000
 13 #define maxn 100000+5
 14 #define maxm 1000000+5
 15 #define eps 1e-10
 16 #define ll long long
 17 #define pa pair<int,int>
 18 #define for0(i,n) for(int i=0;i<=(n);i++)
 19 #define for1(i,n) for(int i=1;i<=(n);i++)
 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 23 #define mod 1000000007
 24 #define mid ((l+r)>>1)
 25 using namespace std;
 26 inline int read()
 27 {
 28     int x=0,f=1;char ch=getchar();
 29     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 30     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 31     return x*f;
 32 }
 33 int  n,m,s,t,cnt,maxflow,tot=1,head[maxm],cur[maxm],h[maxm];
 34 queue<int>q;
 35 int rt[maxn],lc[maxm],rc[maxm];
 36 struct edge{int go,next,v;}e[maxm];
 37 vector<int> son[maxn];
 38 inline void add(int x,int y,int v)
 39 {
 40     e[++tot]=(edge){y,head[x],v};head[x]=tot;
 41     e[++tot]=(edge){x,head[y],0};head[y]=tot;
 42 }
 43 bool bfs()
 44 {
 45     for(int i=0;i<=cnt;i++)h[i]=-1;
 46     q.push(s);h[s]=0;
 47     while(!q.empty())
 48     {
 49         int x=q.front();q.pop();
 50         for(int i=head[x];i;i=e[i].next)
 51          if(e[i].v&&h[e[i].go]==-1)
 52          {
 53             h[e[i].go]=h[x]+1;q.push(e[i].go);
 54          }
 55     }
 56     return h[t]!=-1;
 57 }
 58 int dfs(int x,int f)
 59 {
 60     if(x==t) return f;
 61     int tmp,used=0;
 62     for(int i=cur[x];i;i=e[i].next)
 63      if(e[i].v&&h[e[i].go]==h[x]+1)
 64     {
 65         tmp=dfs(e[i].go,min(e[i].v,f-used));
 66         e[i].v-=tmp;if(e[i].v)cur[x]=i;
 67         e[i^1].v+=tmp;used+=tmp;
 68         if(used==f)return f;       
 69     }
 70     if(!used) h[x]=-1;
 71     return used;
 72 }
 73 void dinic()
 74 {
 75     maxflow=0;
 76     while(bfs())
 77     {
 78         for (int i=0;i<=cnt;i++)cur[i]=head[i];maxflow+=dfs(s,inf);
 79     }
 80 }
 81 inline void insert(int x)
 82 {
 83     int l,r;
 84     for(l=1,r=n,++cnt;l<r;++cnt)
 85      if(x<=mid)
 86      {
 87          add(cnt,lc[cnt]=cnt+1,inf);
 88          r=mid;
 89      }else
 90      {
 91          add(cnt,rc[cnt]=cnt+1,inf);
 92          l=mid+1;
 93      } 
 94     add(cnt,t,1);
 95 }
 96 inline int merge(int x,int y,int l,int r)
 97 {
 98     if(x*y==0)return x+y;
 99     int k=++cnt;
100     if(l==r)add(k,x,inf),add(k,y,inf);
101     else
102     {
103         add(k,lc[k]=merge(lc[x],lc[y],l,mid),inf);
104         add(k,rc[k]=merge(rc[x],rc[y],mid+1,r),inf);
105     }
106     return k;
107 }
108 inline void dfs(int x)
109 {
110     if(!son[x].size())return;
111     for(int i=son[x].size()-1;~i;i--)
112      {
113       dfs(son[x][i]);
114       rt[x]=merge(rt[x],rt[son[x][i]],1,n);
115      } 
116 }
117 inline void query(int k,int l,int r,int x,int y)
118 {
119     if(!k)return;
120     if(l==x&&r==y){add(cnt,k,inf);return;}
121     if(y<=mid)query(lc[k],l,mid,x,y);
122     else if(x>mid)query(rc[k],mid+1,r,x,y);
123     else query(lc[k],l,mid,x,mid),query(rc[k],mid+1,r,mid+1,y);
124 }
125 int main()
126 {
127     freopen("input.txt","r",stdin);
128     freopen("output.txt","w",stdout);
129     n=read();m=read();s=0;t=1;cnt=t;
130     for2(i,2,n)son[read()].push_back(i);
131     for1(i,n)rt[i]=cnt+1,insert(read());
132     dfs(1);
133     while(m--)
134     {
135         int l=read(),r=read(),x=read(),y=read();
136         add(s,++cnt,y);
137         query(rt[x],1,n,l,r);
138     }
139     dinic();
140     cout<<maxflow<<endl;
141     return 0;
142 }
View Code

3681: Arietta

Time Limit: 20 Sec  Memory Limit: 64 MB
Submit: 64  Solved: 28
[Submit][Status]

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

原文地址:https://www.cnblogs.com/zyfzyf/p/4197839.html