码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3681 线段树合并+网络流

时间:2017-03-29 00:59:42      阅读:250      评论:0      收藏:0      [点我收藏+]

标签:ack   ems   ext   ==   线段   vector   tchar   sre   siri   

思路:

暴力建图有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 线段树合并+网络流

标签:ack   ems   ext   ==   线段   vector   tchar   sre   siri   

原文地址:http://www.cnblogs.com/SiriusRen/p/6637688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!