首页 > 代码库 > 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 线段树合并+网络流