bzoj3218: a + b Problem

原来我早就能过了。。。就是数组开小了。。。。

这是一个最小割的题

但是因为加了线段树优化构图变得恶心了

构图的时候需要注意的:同层的点向前建边,插入的链上的每一个点都要和当前的i位置连边

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int inf=(1<<30);
 
struct node
{
    int x,y,c,next;
}a[2100000];int len,last[110000];
void ins(int x,int y,int c)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;
     
    len++;
    a[len].x=y;a[len].y=x;a[len].c=0;
    a[len].next=last[y];last[y]=len;
}
int h[110000],st,ed;
int list[110000];
bool bt_h()
{
    memset(h,0,sizeof(h));h[st]=1;
    int head=1,tail=2;list[1]=st;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(a[k].c>0&&h[y]==0)
            {
                h[y]=h[x]+1;
                list[tail++]=y;
            }
        }
        head++;
    }
    return h[ed]!=0;
}
int findflow(int x,int f)
{
    if(x==ed)return f;
    int s=0;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(a[k].c>0&&h[y]==h[x]+1&&s<f)
        {
            int t=findflow(y,min(a[k].c,f-s));
            s+=t;a[k].c-=t;a[k^1].c+=t;
        }
    }
    if(s==0)h[x]=0;
    return s;
}
 
//-------------------------findflow-----------------------------------
 
int n;
struct trnode
{
    int lc,rc;
}tr[2100000];int trlen,rt[51000];
int maketree(int x,int y,int l,int r,int p,int id)
{
    if(y!=0)ins(x+ed,y+ed,inf);
    ins(x+ed,id,inf);
    if(l<r)
    {
        int mid=(l+r)/2,t;
        if(p<=mid)
        {
            tr[x].lc=++trlen;tr[x].rc=tr[y].rc;
            maketree(tr[x].lc,tr[y].lc,l,mid,p,id);
        }
        else
        {
            tr[x].lc=tr[y].lc;tr[x].rc=++trlen;
            maketree(tr[x].rc,tr[y].rc,mid+1,r,p,id);
        }
    }
}
void findroot(int now,int L,int R,int l,int r,int id)
{
    if(now==0)return ;
    if(L==l&&R==r)
    {
        ins(id,now+ed,inf);
        return ;
    }
    int mid=(L+R)/2;
    int lc=tr[now].lc,rc=tr[now].rc;
         if(r<=mid)  findroot(lc,L,mid,l,r,id);
    else if(mid+1<=l)findroot(rc,mid+1,R,l,r,id);
    else findroot(lc,L,mid,l,mid,id),findroot(rc,mid+1,R,mid+1,r,id);
}
 
struct point{int id,b,w,l,r,p;}p[51000];
int lslen,ls[51000];
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",&n); st=n*2+1,ed=n*2+2;
    lslen=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d%d%d",&p[i].id,&p[i].b,&p[i].w,&p[i].l,&p[i].r,&p[i].p);
        ls[++lslen]=p[i].id,ls[++lslen]=p[i].l,ls[++lslen]=p[i].r;
    }
    sort(ls+1,ls+lslen+1);
    lslen=unique(ls+1,ls+lslen+1)-ls-1; len=1;
    for(int i=1;i<=n;i++)
    {
        p[i].id=lower_bound(ls+1,ls+lslen+1,p[i].id)-ls;
        p[i].l=lower_bound(ls+1,ls+lslen+1,p[i].l)-ls;
        p[i].r=upper_bound(ls+1,ls+lslen+1,p[i].r)-ls-1;  
    }
         
    //-------------------------LSH----------------------------
     
    int sum=0;
    trlen=0;memset(rt,0,sizeof(rt));
    for(int i=1;i<=n;i++)
    {
        sum+=p[i].w+p[i].b;
         
        ins(st,i,p[i].b);
        ins(i,i+n,p[i].p);
        ins(i,ed,p[i].w);
         
        rt[i]=++trlen;
        maketree(rt[i],rt[i-1],1,lslen,p[i].id,i);
        if(i!=1)findroot(rt[i-1],1,lslen,p[i].l,p[i].r,i+n);
    }
     
    //-------------------composition---------------------------
     
    int ans=0;
    while(bt_h())
    {
        ans+=findflow(st,999999999);
    }
    printf("%d\n",sum-ans);
    return 0;
}

 

posted @ 2019-01-06 18:17  AKCqhzdy  阅读(165)  评论(0编辑  收藏  举报