首页 > 代码库 > BZOJ 3681 线段树合并+网络流
BZOJ 3681 线段树合并+网络流
思路:
暴力建图有n*m条边
考虑怎么优化
(那就只能加个线段树了呗)
然后我就不会写了.....
抄了一波题解
//By SiriusRen#include <bits/stdc++.h>using namespace std;const int N=10050,M=N*100,inf=0x3f3f3f3f;vector<int>vec[N];int n,m,first[M],next[M],v[M],w[M],tot,cnt=2,S=1,T=2;int lson[M],rson[M],root[N],jy,vis[M];int read(){ char p=getchar();int x=0; while(p<‘0‘||p>‘9‘)p=getchar(); while(p>=‘0‘&&p<=‘9‘)x=x*10+p-‘0‘,p=getchar(); return x;}void Add(int x,int y,int z){v[tot]=y,w[tot]=z,next[tot]=first[x],first[x]=tot++;}void add(int x,int y,int z){Add(x,y,z),Add(y,x,0);}int insert(int l,int r,int pos,int num){ pos=++cnt; if(l==r){add(cnt,T,1);return pos;} int mid=(l+r)>>1; if(mid<num)add(pos,rson[pos]=insert(mid+1,r,rson[pos],num),inf); else add(pos,lson[pos]=insert(l,mid,lson[pos],num),inf); return pos;}int merge(int l,int r,int pos,int last){ if(pos*last==0)return pos+last; int now=++cnt,mid=(l+r)>>1; if(l==r){add(now,pos,inf),add(now,last,inf);return now;} add(now,lson[now]=merge(l,mid,lson[pos],lson[last]),inf); add(now,rson[now]=merge(mid+1,r,rson[pos],rson[last]),inf); return now;}void dfs(int x){ for(int i=0;i<vec[x].size();i++) dfs(vec[x][i]),root[x]=merge(1,n,root[x],root[vec[x][i]]);}void query(int l,int r,int pos,int L,int R){ if(!pos)return; if(l>=L&&r<=R){add(cnt,pos,inf);return;} int mid=(l+r)>>1; if(mid<L)query(mid+1,r,rson[pos],L,R); else if(mid>=R)query(l,mid,lson[pos],L,R); else query(l,mid,lson[pos],L,R),query(mid+1,r,rson[pos],L,R);}bool tell(){ memset(vis,-1,sizeof(vis)); queue<int>q;q.push(S),vis[S]=0; while(!q.empty()){ int t=q.front();q.pop(); for(int i=first[t];~i;i=next[i]) if(vis[v[i]]==-1&&w[i])vis[v[i]]=vis[t]+1,q.push(v[i]); }return ~vis[T];}int zeng(int x,int y){ if(x==T)return y; int r=0; for(int i=first[x];~i;i=next[i])if(vis[v[i]]==vis[x]+1&&w[i]){ int t=zeng(v[i],min(w[i],y-r)); w[i]-=t,w[i^1]+=t,r+=t; }if(!r)vis[x]=-1; return r;}int flow(){int ans=0;while(tell())while(jy=zeng(S,inf))ans+=jy;return ans;}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d",&n,&m); for(int i=2;i<=n;i++)vec[read()].push_back(i); for(int i=1;i<=n;i++)root[i]=insert(1,n,root[i],read()); dfs(1); for(int i=1;i<=m;i++){ int l=read(),r=read(),x=read(),y=read(); cnt++,add(S,cnt,y),query(1,n,root[x],l,r); } printf("%d\n",flow());}
BZOJ 3681 线段树合并+网络流
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。