首先将
S
S
S连向每一个点
i
i
i,容量为
w
[
i
]
w[i]
w[i],表示割这条边点
i
i
i的颜色为黑色;
i
i
i向
T
T
T连容量为
b
[
i
]
b[i]
b[i]的边,表示割这条边点
i
i
i的颜色为白色。对于
j
j
j满足
1
≤
j
<
i
1\leq j<i
1≤j<i且
a
[
j
]
∈
[
l
[
i
]
,
r
[
i
]
]
a[j]\in [l[i],r[i]]
a[j]∈[l[i],r[i]],连接
i
′
i'
i′,容量为
∞
\infty
∞;最后每一个
i
′
i'
i′向
i
i
i连一条容量为
p
[
i
]
p[i]
p[i]的边,这样我们就可以表示出一个奇怪的点的情况了。
但是这样建图的话边数是
O
(
n
2
)
O(n^2)
O(n2)的,时间和空间都无法承受。
然后我们可以发现,使
i
i
i可能成为奇怪的点的
j
j
j,满足一个二维数点的关系,并且下标的范围为一段前缀。
那么我们可以考虑用主席树来优化这个过程,即每一次连边的时候用一段区间和当前的
i
′
i'
i′连边。对于主席树上的节点,从下向上连接容量为
∞
\infty
∞的边即可。
最后边数就被我们优化成
O
(
n
log
n
)
O(n\log n)
O(nlogn)了,问题得到解决。
代码
#include<bits/stdc++.h>#define ll long longusingnamespace std;template<typename T>voidread(T &x){
x =0;int f =1;char c =getchar();while(!isdigit(c)){if(c =='-') f =-1; c =getchar();}while(isdigit(c)) x = x *10+ c -'0', c =getchar(); x *= f;}constint N =10010, M = N *15;const ll inf =1ll<<60;int cnt, tot, rt[N], b[M], l[M], lc[M], rc[M], cur[M], head[M];struct Info {int a, b, w, l, r, p;} q[N];struct Edge {int next, num; ll c;} e[M *3];voidadd(int x,int y, ll c){e[++cnt]=(Edge){head[x], y, c}, head[x]= cnt;}voidAdd(int x,int y, ll c){add(x, y, c),add(y, x,0);}boolbfs(int s,int t){for(int i = s; i <= tot; i++) l[i]=-1;
queue <int> q; q.push(s), l[s]=0;while(!q.empty()){int x = q.front(); q.pop();for(int p = head[x]; p; p = e[p].next){int k = e[p].num; ll c = e[p].c;if(c && l[k]==-1) l[k]= l[x]+1, q.push(k);}}return l[t]!=-1;}
ll dfs(int x,int t, ll lim){if(x == t)return lim; ll ret =0;for(int&p = cur[x]; p; p = e[p].next){int k = e[p].num; ll c = e[p].c;if(c && l[k]== l[x]+1){
ll w =dfs(k, t,min(lim - ret, c));
e[p].c -= w, e[p ^1].c += w, ret += w;if(ret == lim)return ret;}}if(!ret) l[x]=-1;return ret;}
ll dinic(int s,int t){
ll ret =0;while(bfs(s, t)){for(int i = s; i <= tot; i++) cur[i]= head[i];
ret +=dfs(s, t, inf);}return ret;}intins(int k,int l,int r,int x,int id){int ret =++tot; lc[ret]= lc[k], rc[ret]= rc[k];if(l == r){Add(id, ret, inf);if(k)Add(k, ret, inf);return ret;}int mid =(l + r)>>1;if(x <= mid) lc[ret]=ins(lc[k], l, mid, x, id);else rc[ret]=ins(rc[k], mid +1, r, x, id);if(lc[ret])Add(lc[ret], ret, inf);if(rc[ret])Add(rc[ret], ret, inf);return ret;}voidquery(int k,int l,int r,int L,int R,int id){if(!k)return;if(L <= l && r <= R)returnAdd(k, id, inf),void();int mid =(l + r)>>1;if(L <= mid)query(lc[k], l, mid, L, R, id);if(R > mid)query(rc[k], mid +1, r, L, R, id);}intmain(){int n, len =0;read(n); ll ans =0;int s =0, t =2* n +1; cnt =1, tot =2* n +1;for(int i =1; i <= n; i++){read(q[i].a),read(q[i].b),read(q[i].w);read(q[i].l),read(q[i].r),read(q[i].p);
ans += q[i].b + q[i].w;Add(s, i, q[i].w),Add(i, t, q[i].b),Add(i + n, i, q[i].p);
b[++len]= q[i].a, b[++len]= q[i].l, b[++len]= q[i].r;}sort(b +1, b + len +1), len =unique(b +1, b + len +1)- b -1;for(int i =1; i <= n; i++)
q[i].a =lower_bound(b +1, b + len +1, q[i].a)- b,
q[i].l =lower_bound(b +1, b + len +1, q[i].l)- b,
q[i].r =lower_bound(b +1, b + len +1, q[i].r)- b;for(int i =1; i <= n; i++){query(rt[i -1],1, len, q[i].l, q[i].r, i + n);
rt[i]=ins(rt[i -1],1, len, q[i].a, i);}
cout << ans -dinic(s, t)<<"\n";return0;}