题解:
数据结构来优化网络流,貌似都是用一段区间来表示一个点,然后各种乱搞。。。
发现主席树好吊。。。在树上建主席树貌似有三种方法:
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 }
3681: Arietta
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 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
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