[BZOJ 3218]a + b Problem

又是一道主席树优化网络流的好题

按约大爷的教导,源点为白,汇点为黑,搞成最小割

发现暴力连边要爆炸,但是要连的点在线段树中都构成了一个区间,果断主席树优化之

为什么不用一般线段树?

因为要满足 j<i ,这里的可持久化并不是为了查询过去的值,而是为了保留过去的值不与后来弄混~

如果有两个点的 a[i] 相同在线段树里怎么搞?

很简单,从 a[i] 向 a[j] 连一条 inf 的流即可

 

不过——为什么题目名字那么坑啊啊啊啊啊啊?!!!!!

    这种题是不是非要来卡空间不然不痛快是吗?!!!!!

 

  1 #include <cstdio>

  2 #include <cstring>

  3 const int sizeOfSegment=500005;

  4 const int sizeOfEdge=1000001;

  5 const int sizeOfPoint=500005;

  6 const int sizeOfCell=5005;

  7 const int inf=1000000000;

  8 

  9 inline int min(int, int);

 10 inline int getint();

 11 inline void putint(int);

 12 

 13 int S, T;

 14 int V;

 15 int n;

 16 int a[sizeOfCell], b[sizeOfCell], w[sizeOfCell], l[sizeOfCell], r[sizeOfCell], p[sizeOfCell];

 17 

 18 struct edge {int point, flow; edge * next, * pair;};

 19 edge memory_edge[sizeOfEdge], * port_edge=memory_edge;

 20 edge * e[sizeOfPoint];

 21 inline edge * newedge(int, int, edge * );

 22 inline void link(int, int, int);

 23 int h[sizeOfPoint], gap[sizeOfPoint];

 24 inline bool bfs();

 25 inline int isap();

 26 

 27 struct seg {int p; seg * l, * r;};

 28 seg memory_seg[sizeOfSegment], * port_seg=memory_seg;

 29 seg * t;

 30 inline seg * newseg(seg * =NULL);

 31 seg * insert(seg * , int, int, int, int);

 32 void query(seg * , int, int, int, int, int);

 33 

 34 int main()

 35 {

 36     int ans=0;

 37 

 38     n=getint();

 39     S=0; T=n+1; V=n+1;

 40     for (int i=1;i<=n;i++)

 41     {

 42         a[i]=getint(), b[i]=getint(), w[i]=getint(), l[i]=getint(), r[i]=getint(), p[i]=getint();

 43         ans+=b[i]+w[i];

 44         link(S, i, b[i]); link(i, T, w[i]);

 45         link(i, ++V, p[i]);

 46         query(t, 0, inf, l[i], r[i], V);

 47         t=insert(t, 0, inf, a[i], i);

 48     }

 49 

 50     ans-=isap();

 51     putint(ans);

 52 

 53     return 0;

 54 }

 55 inline int min(int x, int y)

 56 {

 57     return x<y?x:y;

 58 }

 59 inline int getint()

 60 {

 61     register int num=0;

 62     register char ch;

 63     do ch=getchar(); while (ch<'0' || ch>'9');

 64     do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');

 65     return num;

 66 }

 67 inline void putint(int num)

 68 {

 69     char stack[11];

 70     register int top=0;

 71     if (num==0) stack[top=1]='0';

 72     for ( ;num;num/=10) stack[++top]=num%10+'0';

 73     for ( ;top;top--) putchar(stack[top]);

 74     putchar('\n');

 75 }

 76 inline edge * newedge(int point, int flow, edge * next)

 77 {

 78     edge * ret=port_edge++;

 79     ret->point=point; ret->flow=flow; ret->next=next;

 80     return ret;

 81 }

 82 inline void link(int u, int v, int f)

 83 {

 84     e[u]=newedge(v, f, e[u]); e[v]=newedge(u, 0, e[v]);

 85     e[u]->pair=e[v]; e[v]->pair=e[u];

 86 }

 87 inline bool bfs()

 88 {

 89     static int q[sizeOfPoint];

 90     static int l, r;

 91     memset(h, 0xFF, sizeof(h)); h[T]=0;

 92     l=r=0;

 93     for (q[r++]=T;l<r;l++)

 94     {

 95         int u=q[l];

 96         ++gap[h[u]];

 97         for (edge * i=e[u];i;i=i->next) if (h[i->point]==-1)

 98         {

 99             h[i->point]=h[u]+1;

100             q[r++]=i->point;

101         }

102     }

103     return h[S]>-1;

104 }

105 inline int isap()

106 {

107     static edge * t[sizeOfPoint], * p[sizeOfPoint];

108     static int aug[sizeOfPoint];

109     int flow=0, hmin=0;

110 

111     if (!bfs()) return 0;

112 

113     memcpy(t, e, sizeof(e)); memset(p, 0, sizeof(p));

114     aug[S]=inf;

115     for (int u=S;h[S]<V; )

116     {

117         if (u==T)

118         {

119             flow+=aug[T];

120             for (edge * i=p[T];i;i=p[i->point])

121                 aug[i->point]-=aug[T], i->pair->flow-=aug[T], i->flow+=aug[T];

122             for (edge * i=p[T];i;i=p[i->point]) if (aug[i->point])

123             {

124                 u=i->point;

125                 break;

126             }

127         }

128 

129         edge *& i=t[u];

130         for ( ;i && (!i->flow || h[i->point]+1!=h[u]);i=i->next);

131         if (i)

132         {

133             aug[i->point]=min(aug[u], i->flow); p[i->point]=i->pair;

134             u=i->point;

135         }

136         else

137         {

138             if (!--gap[h[u]]) break;

139             hmin=V;

140             for (edge * j=e[u];j;j=j->next) if (j->flow && h[j->point]+1<hmin)

141             {

142                 hmin=h[j->point]+1;

143                 t[u]=j;

144             }

145             ++gap[h[u]=hmin];

146             u=u==S?S:p[u]->point;

147         }

148     }

149 

150     return flow;

151 }

152 inline seg * newseg(seg * t)

153 {

154     seg * newt=port_seg++;

155     newt->p=++V; newt->l=t?t->l:NULL; newt->r=t?t->r:NULL;

156     return newt;

157 }

158 seg * insert(seg * t, int l, int r, int p, int v)

159 {

160     seg * newt=newseg(t);

161     if (l==r)

162     {

163         if (t) link(newt->p, t->p, inf);

164         link(newt->p, v, inf);

165     }

166     else

167     {

168         int m=(l+r)>>1;

169         if (p<=m)

170         {

171             newt->l=insert(newt->l, l, m, p, v), link(newt->p, newt->l->p, inf);

172             if (newt->r) link(newt->p, newt->r->p, inf);

173         }

174         else

175         {

176             newt->r=insert(newt->r, m+1, r, p, v), link(newt->p, newt->r->p, inf);

177             if (newt->l) link(newt->p, newt->l->p, inf);

178         }

179     }

180 

181     return newt;

182 }

183 void query(seg * t, int l, int r, int ql, int qr, int v)

184 {

185     if (!t) return ;

186     if (l==ql && r==qr) link(v, t->p, inf);

187     else

188     {

189         int m=(l+r)>>1;

190         if (qr<=m) query(t->l, l, m, ql, qr, v);

191         else if (ql>=m+1) query(t->r, m+1, r, ql, qr, v);

192         else query(t->l, l, m, ql, m, v), query(t->r, m+1, r, m+1, qr, v);

193     }

194 }
改数组改到想去死

 

尝试着用了用 Data Display Debugger 觉得是很强大但是总觉得也很不顺手?

不过反正有了这个我是不想再去用 gdb 了……

 

你可能感兴趣的:(ZOJ)