bzoj 3681 Arietta
题目大意:
一棵树上每个点有权值,m次操作 每次可以在$d_i$的节点的子树中选择$t_i$个$l_i \le val \le r_i$的点
求这么多次操作后最多选多少个点(每个点只能被选一次
思路:
暴力建图非常显然
$S \rightarrow New (val=t)\rightarrow (x \in {[l,r]∩tree_d}) \rightarrow T$
优化边数的时候可以使用$dsu\space on\space tree$即对于点$x$的子树,可以继承重儿子然后对于不在这条重链上的点暴力加入
使用主席树来实现(需要注意
对于整棵树建完主席树后再加入操作的边
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #include<set> 11 #define ll long long 12 #define inf 2139062143 13 #define MAXN 10100 14 #define DMAXN 551000 15 #define DMAXM 1000100 16 #define MOD 998244353 17 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i) 18 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i) 19 #define ren for(register int i=fst[x];i;i=nxt[i]) 20 #define pb(i,x) vec[i].push_back(x) 21 #define pls(a,b) (a+b)%MOD 22 #define mns(a,b) (a-b+MOD)%MOD 23 #define mul(a,b) (1LL*(a)*(b))%MOD 24 using namespace std; 25 inline int read() 26 { 27 int x=0,f=1;char ch=getchar(); 28 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 29 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 30 return x*f; 31 } 32 int n,m,S,T,fst[MAXN],nxt[MAXN],to[MAXN]; 33 namespace D 34 { 35 int fst[DMAXN],nxt[DMAXM<<1],to[DMAXM<<1],val[DMAXM<<1],cnt; 36 int q[DMAXN],l,r,vis[DMAXN],tot,dis[DMAXN],cur[DMAXM<<1]; 37 void mem() {memset(fst,0,sizeof(fst));cnt=1;} 38 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;} 39 void ins(int u,int v,int w) {add(u,v,w);add(v,u,0);} 40 int bfs() 41 { 42 vis[T]=++tot,q[l=r=1]=T,dis[T]=0;int x; 43 while(l<=r) 44 { 45 x=q[l++];ren if(vis[to[i]]!=tot&&val[i^1]) 46 vis[to[i]]=tot,dis[to[i]]=dis[x]+1,q[++r]=to[i]; 47 } 48 return vis[S]==tot; 49 } 50 int dfs(int x,int a) 51 { 52 if(!a||x==T) return a;int f,flw=0; 53 for(int &i=cur[x];i&&a;i=nxt[i]) 54 if(dis[to[i]]==dis[x]-1&&val[i]&&(f=dfs(to[i],min(a,val[i])))) 55 val[i]-=f,val[i^1]+=f,flw+=f,a-=f; 56 return flw; 57 } 58 int solve(int sum) 59 { 60 int f,ans=0;while(bfs()) 61 {rep(i,0,sum) cur[i]=fst[i];while(f=dfs(S,inf)) ans+=f;} 62 return ans; 63 } 64 }; 65 int fa[MAXN],sz[MAXN],hvs[MAXN],cnt,tot,val[MAXN],rt[MAXN],ls[MAXN*60],rs[MAXN*60]; 66 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 67 void mdf(int &k,int kk,int l,int r,int a,int t) 68 { 69 k=++tot,ls[k]=ls[kk],rs[k]=rs[kk]; 70 if(l==r){D::ins(k+n,t,inf);if(kk) D::ins(k+n,kk+n,inf);return ;}int mid=l+r>>1; 71 if(a<=mid) mdf(ls[k],ls[kk],l,mid,a,t); 72 else mdf(rs[k],rs[kk],mid+1,r,a,t); 73 } 74 void query(int k,int l,int r,int a,int b,int x) 75 { 76 if(!k) return ;if(l==a&&r==b) {D::ins(tot+n,k+n,x);return ;} 77 int mid=l+r>>1; 78 if(b<=mid) query(ls[k],l,mid,a,b,x); 79 else if(a>mid) query(rs[k],mid+1,r,a,b,x); 80 else {query(ls[k],l,mid,a,mid,x);query(rs[k],mid+1,r,mid+1,b,x);} 81 } 82 void Get(int x,int anc) 83 { 84 mdf(rt[anc],rt[anc],1,n,val[x],x); 85 ren Get(to[i],anc); 86 } 87 void dfs(int x) 88 { 89 sz[x]=1;ren 90 { 91 dfs(to[i]),sz[x]+=sz[to[i]]; 92 if(sz[to[i]]>sz[hvs[x]]) hvs[x]=to[i]; 93 } 94 mdf(rt[x],rt[hvs[x]],1,n,val[x],x); 95 ren if(to[i]^hvs[x]) Get(to[i],x); 96 } 97 int main() 98 { 99 n=read(),m=read();int a,b,c,d;D::mem(); 100 rep(i,2,n) fa[i]=read(),add(fa[i],i);rep(i,1,n) val[i]=read();dfs(1); 101 rep(i,1,tot) {if(ls[i]) D::ins(i+n,ls[i]+n,inf);if(rs[i]) D::ins(i+n,rs[i]+n,inf);} 102 S=0,T=n+tot+1; 103 rep(i,1,n) D::ins(i,T,1);tot++; 104 while(m--) 105 { 106 a=read(),b=read(),c=read(),d=read(),tot++;D::ins(S,tot+n,d); 107 query(rt[c],1,n,a,b,d); 108 } 109 printf("%d\n",D::solve(tot+n)); 110 }