【bzoj3218】 a + b Problem
http://www.lydsy.com/JudgeOnline/problem.php?id=3218 (题目链接)
题意
给${n}$个格子涂白或黑色,白则${w_i}$,黑则${b_i}$的好看度,若对于黑格${i}$存在:${白格j,使得1 \leq j<i,l_i \leq a_j \leq r_i}$,则损失${p_i}$,问最大的好看度。
Solution
不会。。上题解:PoPoQQQ
指针的主席树看得我眼泪掉下来啊T_T,完全不会指针啊T_T
细节
当主席树建树递归到最后一层时,记得将之前的${i-1}$号主席树上连向该节点的边继承过来。(不好描述,已在代码中标记)
代码
// bzoj3218 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=5010,maxm=1000010; struct edge {int to,next,w;}e[maxm]; struct Segtree {int ls,rs;}tr[maxm]; int head[maxm],d[maxm]; int cnt=1,es,et; int n,L[maxn],R[maxn],a[maxn],tmp[maxm]; int size,T[maxm]; LL ans; void link(int u,int v,int w) { e[++cnt]=(edge){v,head[u],w};head[u]=cnt; e[++cnt]=(edge){u,head[v],0};head[v]=cnt; } bool bfs() { memset(d,-1,sizeof(d)); queue<int> q;q.push(es);d[es]=0; while (!q.empty()) { int x=q.front();q.pop(); for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]<0) { d[e[i].to]=d[x]+1; q.push(e[i].to); } } return d[et]>0; } int dfs(int x,int f) { if (x==et || f==0) return f; int w,used=0; for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]==d[x]+1) { w=dfs(e[i].to,min(e[i].w,f-used)); used+=w; e[i].w-=w;e[i^1].w+=w; if (used==f) return used; } if(!used) d[x]=-1; return used; } void Dinic() { while (bfs()) ans-=dfs(es,inf); } void insert(int k,int l,int r,int i) { if (l>R[i] || r<L[i]) return; if (L[i]<=l && r<=R[i]) {link(k+et,n+i,inf);return;} int mid=(l+r)>>1; if (tr[k].ls) insert(tr[k].ls,l,mid,i); if (tr[k].rs) insert(tr[k].rs,mid+1,r,i); } void build(int &rt,int k,int l,int r,int i) { rt=++size; if (l==r) { link(i,rt+et,inf); if (k) link(k+et,rt+et,inf); //细节 return; } int mid=(l+r)>>1; if (a[i]<=mid) tr[rt].rs=tr[k].rs,build(tr[rt].ls,tr[k].ls,l,mid,i); else tr[rt].ls=tr[k].ls,build(tr[rt].rs,tr[k].rs,mid+1,r,i); if (tr[rt].ls) link(tr[rt].ls+et,rt+et,inf); if (tr[rt].rs) link(tr[rt].rs+et,rt+et,inf); } int main() { scanf("%d",&n); es=2*n+1;et=es+1; int tot=0; for (int b,w,p,i=1;i<=n;i++) { scanf("%d%d%d%d%d%d",&a[i],&b,&w,&L[i],&R[i],&p); tmp[++tot]=a[i];tmp[++tot]=L[i];tmp[++tot]=R[i]; link(es,i,w); link(i,et,b); link(i+n,i,p); ans+=w+b; } sort(tmp+1,tmp+1+tot); tot=unique(tmp+1,tmp+1+tot)-tmp-1; for (int i=1;i<=n;i++) { a[i]=lower_bound(tmp+1,tmp+1+tot,a[i])-tmp; L[i]=lower_bound(tmp+1,tmp+1+tot,L[i])-tmp; R[i]=lower_bound(tmp+1,tmp+1+tot,R[i])-tmp; if (i>1) insert(T[i-1],1,tot,i); build(T[i],T[i-1],1,tot,i); } Dinic(); printf("%lld",ans); return 0; }
This passage is made by MashiroSky.