做法见dalao博客 geng4512的博客, 思路就是用线段树上的结点来进行区间连边.因为有一个只能往前面连的限制,所以还要可持久化.(duliu)

一直以来我都是写dinicdinicdinic做最大流,感觉加上弧优化等等效率还是蛮高的…但是这道题点数边数都是 nlognlognlog 级别的,让我发现还是SAP(ISAP?SAP(ISAP?SAP(ISAP?)最快啊…

  • 这是dinicdinicdinic AC代码(加上弧优化 4112 ms, 不加 4072 ms)

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    template<typename T>inline void read(T &num) {
    char ch; while((ch=getchar())<'0'||ch>'9');
    for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
    }
    const int N = 5005;
    const int MAXN = N*20;
    const int MAXM = 1000005;
    const int inf = 1e9;
    int n, fir[MAXN], S, T, cnt, sz;
    struct edge { int to, nxt, c; }e[MAXM];
    inline void add(int u, int v, int cc) {
    e[cnt] = (edge){ v, fir[u], cc }; fir[u] = cnt++;
    e[cnt] = (edge){ u, fir[v], 0 }; fir[v] = cnt++;
    }
    int dis[MAXN], vis[MAXN], info[MAXN], cur, q[MAXN];
    inline bool bfs() {
    int head = 0, tail = 0;
    vis[S] = ++cur; q[tail++] = S; dis[S] = 0;
    while(head < tail) {
    int u = q[head++];
    for(int i = fir[u]; ~i; i = e[i].nxt)
    if(e[i].c && vis[e[i].to] != cur)
    vis[e[i].to] = cur, dis[e[i].to] = dis[u] + 1, q[tail++] = e[i].to;
    }
    return vis[T] == cur;
    }
    int dfs(int u, int Max) {
    if(u == T || !Max) return Max;
    int flow=0, delta;
    for(int i = fir[u]; ~i; i = e[i].nxt)
    if(e[i].c && dis[e[i].to] == dis[u] + 1 && (delta=dfs(e[i].to, min(e[i].c, Max-flow)))) {
    e[i].c -= delta, e[i^1].c += delta, flow += delta;
    if(flow == Max) return flow;
    }
    if(!flow) dis[u] = -1;
    return flow;
    }
    inline int dinic() {
    int flow=0, x;
    while(bfs()) while((x=dfs(S, inf))) flow+=x;
    return flow;
    }
    int A[N], B[N], W[N], L[N], R[N], P[N], Q[N*3], sum, tot;
    int rt[MAXN], ch[MAXN][2]; void Insert(int &rt, int p, int l, int r, int i) {
    rt = ++sz;
    if(l == r) {
    add(rt+T, i, inf);
    if(p) add(rt+T, p+T, inf);
    return;
    }
    int mid = (l + r) >> 1;
    if(A[i] <= mid) ch[rt][1] = ch[p][1], Insert(ch[rt][0], ch[p][0], l, mid, i);
    else ch[rt][0] = ch[p][0], Insert(ch[rt][1], ch[p][1], mid+1, r, i);
    if(ch[rt][0]) add(rt+T, ch[rt][0]+T, inf);
    if(ch[rt][1]) add(rt+T, ch[rt][1]+T, inf);
    } void Link(int rt, int l, int r, int i) {
    if(L[i] <= l && r <= R[i]) { add(i+n, rt+T, inf); return; }
    int mid = (l + r) >> 1;
    if(L[i] <= mid && ch[rt][0]) Link(ch[rt][0], l, mid, i);
    if(R[i] > mid && ch[rt][1]) Link(ch[rt][1], mid+1, r, i);
    } int main () {
    memset(fir, -1, sizeof fir);
    read(n); S = 0, T = 2*n+1;
    for(int i = 1; i <= n; ++i)
    read(A[i]), read(B[i]), read(W[i]),
    read(L[i]), read(R[i]), read(P[i]),
    Q[++tot] = A[i], Q[++tot] = L[i], Q[++tot] = R[i], sum += B[i] + W[i];
    sort(Q + 1, Q + tot + 1);
    tot = unique(Q + 1, Q + tot + 1) - (Q + 1);
    for(int i = 1; i <= n; ++i)
    A[i] = lower_bound(Q + 1, Q + tot + 1, A[i]) - Q,
    L[i] = lower_bound(Q + 1, Q + tot + 1, L[i]) - Q,
    R[i] = lower_bound(Q + 1, Q + tot + 1, R[i]) - Q,
    add(S, i, B[i]), add(i, T, W[i]), add(i, i+n, P[i]);
    for(int i = 1; i <= n; ++i) {
    if(i > 1) Link(rt[i-1], 1, tot, i);
    Insert(rt[i], rt[i-1], 1, tot, i);
    }
    sz += T;
    printf("%d\n", sum-dinic());
    }
  • 然后下面是SAP(ISAP?)SAP(ISAP?)SAP(ISAP?)的AC代码(444 ms!!!快了10倍!!)

#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<typename T>inline void read(T &num) {
char ch; while((ch=getc())<'0'||ch>'9');
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getc());
}
const int N = 5005;
const int MAXN = N*20;
const int MAXM = 1000005;
const int inf = 1e9;
int n, fir[MAXN], S, T, cnt, sz;
struct edge { int to, nxt, c; }e[MAXM];
inline void add(int u, int v, int cc) {
e[cnt] = (edge){ v, fir[u], cc }; fir[u] = cnt++;
e[cnt] = (edge){ u, fir[v], 0 }; fir[v] = cnt++;
}
int A[N], B[N], W[N], L[N], R[N], P[N], Q[N*3], sum, tot;
int rt[MAXN], ch[MAXN][2];
void Insert(int &rt, int p, int l, int r, int i) {
rt = ++sz;
if(l == r) {
add(rt+T, i, inf);
if(p) add(rt+T, p+T, inf);
return;
}
int mid = (l + r) >> 1;
if(A[i] <= mid) ch[rt][1] = ch[p][1], Insert(ch[rt][0], ch[p][0], l, mid, i);
else ch[rt][0] = ch[p][0], Insert(ch[rt][1], ch[p][1], mid+1, r, i);
if(ch[rt][0]) add(rt+T, ch[rt][0]+T, inf);
if(ch[rt][1]) add(rt+T, ch[rt][1]+T, inf);
}
void Link(int rt, int l, int r, int i) {
if(L[i] <= l && r <= R[i]) { add(i+n, rt+T, inf); return; }
int mid = (l + r) >> 1;
if(L[i] <= mid && ch[rt][0]) Link(ch[rt][0], l, mid, i);
if(R[i] > mid && ch[rt][1]) Link(ch[rt][1], mid+1, r, i);
}
namespace SAP {
int d[MAXN], vd[MAXN]; //sz表示总点数
int Aug(int u, int Max) {
if(u == T) return Max;
int delta, dmin = sz - 1, flow = 0, v;
for(int i = fir[u]; ~i; i = e[i].nxt) if(e[i].c) {
v = e[i].to;
if(d[v] + 1 == d[u]) {
delta = Aug(v, min(Max-flow, e[i].c));
e[i].c -= delta, e[i^1].c += delta, flow += delta;
if(d[S] >= sz || flow == Max) return flow;
}
if(dmin > d[v]) dmin = d[v];
}
if(!flow) {
--vd[d[u]];
if(!vd[d[u]]) d[S] = sz;
++vd[d[u] = dmin + 1];
}
return flow;
}
int sap() {
memset(d, 0, sizeof d);
memset(vd, 0, sizeof vd);
int flow = 0;
while(d[S] < sz)
flow += Aug(S, inf);
return flow;
}
}
int main () {
memset(fir, -1, sizeof fir);
read(n); S = 0, T = 2*n+1;
for(int i = 1; i <= n; ++i)
read(A[i]), read(B[i]), read(W[i]),
read(L[i]), read(R[i]), read(P[i]),
Q[++tot] = A[i], Q[++tot] = L[i], Q[++tot] = R[i], sum += B[i] + W[i];
sort(Q + 1, Q + tot + 1);
tot = unique(Q + 1, Q + tot + 1) - (Q + 1);
for(int i = 1; i <= n; ++i)
A[i] = lower_bound(Q + 1, Q + tot + 1, A[i]) - Q,
L[i] = lower_bound(Q + 1, Q + tot + 1, L[i]) - Q,
R[i] = lower_bound(Q + 1, Q + tot + 1, R[i]) - Q,
add(S, i, B[i]), add(i, T, W[i]), add(i, i+n, P[i]);
for(int i = 1; i <= n; ++i) {
if(i > 1) Link(rt[i-1], 1, tot, i);
Insert(rt[i], rt[i-1], 1, tot, i);
}
sz += T;
printf("%d\n", sum-SAP::sap());
}

BZOJ 3218 A + B Problem (可持久化线段树+最小割)的更多相关文章

  1. [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)

    [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...

  2. UOJ#77. A+B Problem [可持久化线段树优化建边 最小割]

    UOJ#77. A+B Problem 题意:自己看 接触过线段树优化建图后思路不难想,细节要处理好 乱建图无果后想到最小割 白色和黑色只能选一个,割掉一个就行了 之前选白色必须额外割掉一个p[i], ...

  3. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  4. 【BZOJ3218】a + b Problem 可持久化线段树优化建图

    [BZOJ3218]a + b Problem 题解:思路很简单,直接最小割.S->i,容量为Bi:i->T,容量为Wi:所有符合条件的j->new,容量inf:new->i, ...

  5. BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)

    首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ...

  6. bzoj 4504: K个串 可持久化线段树+堆

    题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...

  7. bzoj 3514: GERALD07加强版 lct+可持久化线段树

    题目大意: N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 题解: 这道题考试的时候没想出来 于是便爆炸了 结果今天下午拿出昨天准备的题表准备做题的时候 题表里就有这题 ...

  8. BZOJ 3524 [Poi2014]Couriers(可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3524 [题目大意] 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个 ...

  9. BZOJ 2653 middle 二分答案+可持久化线段树

    题目大意:有一个序列,包含多次询问.询问区间左右端点在规定区间里移动所得到的最大中位数的值. 考虑对于每个询问,如何得到最优区间?枚举显然是超时的,只能考虑二分. 中位数的定义是在一个序列中,比中位数 ...

随机推荐

  1. IdentityServer4 学习一

    网上找的关于IdentityServer4的百度脑图 http://naotu.baidu.com/file/75b251257ce27cfa62e0ad7f47b75576?token=e2db61 ...

  2. 用css美化select框

    先上代码: .selectData{ height: 0.42rem; position: absolute; right:.28rem; top:.30rem; //去边框 border: none ...

  3. Java的设计模式(4)--抽象工厂模式

    提供一个创建一系列或相互依赖对象的接口,而无须指定他们具体的类.例如某些系统可能需要为用户提供一系列相关对象,但系统不希望用户直接使用new运算符实例化这些对象,而是应当由系统来控制这些对象的创建,否 ...

  4. 『Python基础』第2节: Python简介及入门

    一. Python介绍 Python是一门高级计算机程序设计语言,1989年,荷兰的Guido von Rossum创造了它.Guido是是一个牛人,1982年,他从阿姆斯特丹大学获得了数学和计算机硕 ...

  5. S03_CH09_DMA_4_Video_Switch视频切换系统

    S03_CH09_DMA_4_Video_Switch视频切换系统 9.1概述 本例程详细创建过程和本季课程第一课<S03_CH01_AXI_DMA_LOOP 环路测试>非常类似,因此如果 ...

  6. 定义别名:typedef和using

    定义别名:

  7. shell习题第22题:

    [题目要求] 加入A服务器可直接ssh到B,不用输入密码.A和B都有一个目录是/data/web/这下有很多文件,我们不知道这下面有多少层目录,但是之前的目录结构和文件是一模一样的.但是现在不确定是否 ...

  8. MVC5项目转.Net Core 2.2学习与填坑记录(1)

    流程都是自己摸索,错误地方随便指正... 老项目过于臃肿,并且所有请求都是提交到一个api中,这样当api挂掉的时候,基本所有的项目都瘫痪掉了. 在4月底的时候,下决心将项目用微服务进行重写,刚开始的 ...

  9. SIFT算法研究

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://underthehood.blog.51cto.com/2531780/65835 ...

  10. 华为Python面试题

    最近在网上偶然看到此题: 有两个序列a,b,大小都为n,序列元素的值任意整形数,无序: 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小 经过一番思索,我试着用穷举法 ...