题目大意:给定
n
道菜,每道菜出现的时间
题解:二分答案+线段树构图+网络流
(据说有贪心做法,为什么大家都那么神呢?=_=)
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
int n,maxx;
int head[161000],nextt[2010000],ver[2010000],edge[2010000],tot=-1,hehe;
int rson[160100],lson[160100],treepoint=1;
int ch[161000];
queue<int> q;
void add(int x,int y,int z)
{
tot++;
nextt[tot]=head[x];
head[x]=tot;
ver[tot]=y;
edge[tot]=z;
}
bool tell()
{
q.push(0);
memset(ch,-1,sizeof ch);
ch[0] = 0;
while (q.size())
{
int x = q.front();q.pop();
for (int i = head[x];i!=-1;i=nextt[i])
if (ch[ver[i]]==-1&&edge[i])
ch[ver[i]]=ch[x]+1,q.push(ver[i]);
}
return ch[treepoint+n+1]!=-1;
}
int zeng(int a,int b)
{
if (a == treepoint+n+1) return b;
int r = 0;
for (int i = head[a];i!=-1;i=nextt[i])
if (ch[ver[i]] == ch[a]+1&&edge[i])
{
int t = zeng(ver[i],min(b-r,edge[i]));
r+=t;edge[i]-=t,edge[i^1]+=t;
}
if (!r) ch[a]=-1;
return r;
}
int judge(int x)
{
for (int i = 0;i <= tot;i+=2)
edge[i] += edge[i^1],edge[i^1]=0;
for (int i = hehe+1;i <= tot;i+=2)
edge[i] = x;
int r = 0,z;
while (tell())
while (z = zeng(0,0x3f3f3f3f))
r+=z;
return r;
}
void maketree(int x,int l,int r)
{
if (l == r) return ;
int mid = (l + r)/2;
lson[x] = ++treepoint;
rson[x] = ++treepoint;
maketree(lson[x],l,mid);
maketree(rson[x],mid+1,r);
}
void maketree2(int x,int l,int r)
{
int mid = (l + r)/2;
if (l == r) {
add(x,treepoint+n+1,1),add(treepoint+n+1,x,0);return ;
}
add(x,lson[x],mid-l+1),add(lson[x],x,0);
add(x,rson[x],r-mid),add(rson[x],x,0);
maketree2(lson[x],l,mid);
maketree2(rson[x],mid+1,r);
}
void add(int x,int l,int r,int ll,int rr,int hehe)
{
if (l > rr || r < ll) return ;
if (ll <= l && r <= rr)
{
add(treepoint+hehe,x,r-l+1);
add(x,treepoint+hehe,0);
return ;
}
int mid = (l + r)/2;
add(lson[x],l,mid,ll,rr,hehe);
add(rson[x],mid+1,r,ll,rr,hehe);
}
int main()
{
memset(head,-1,sizeof head);
cin >> n;maxx = 10000/n;
maketree(1,1,10000);
maketree2(1,1,10000);
for (int i = 1;i <= n;i++)
{
int x,y;scanf("%d%d",&x,&y);y--;x++,y++;maxx = min(maxx,(y-x+1));
add(1,1,10000,x,y,i);
}
hehe = tot;
for (int i = 1;i <= n;i++) add(0,treepoint+i,0),add(treepoint+i,0,0);
int l = 0,r = maxx+1;
while (l < r)
{
int mid = (l + r)/2;
if (judge(mid)==mid*n) l = mid + 1;
else r = mid;
}
cout << (l-1)*n << endl;
}