您的位置:首页 > Web前端

[扫描线 线段树上二分] BZOJ 4411 [Usaco2016 Feb]Load balancing

2016-10-23 12:14 399 查看
第一维扫描线

第二维线段树上二分

好久之前的代码了

#include<cstdio>
#include<cstdlib>
#include<functional>
#include<algorithm>
using namespace std;

inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,10000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

int MAXN;

int S1[400005];
int S2[400005];

inline void update(int* S,int x,int v)
{
x+=MAXN;
S[x]+=v;
while (x>>=1)
S[x]=S[x<<1]+S[x<<1|1];
}

int N,ans;
pair<int,int> A[100005];

inline bool cmp(pair<int,int> A,pair<int,int> B){
return A.second==B.second?A.first<B.first:A.second<B.second;
}

inline void solve(int x,int l1,int r1,int l2,int r2)
{
if (x>MAXN)
{
l1+=S1[x]; l2+=S2[x];
ans=min(ans,max(max(l1,r1),max(l2,r2)));
r1+=S1[x]; r2+=S2[x];
ans=min(ans,max(max(l1,r1),max(l2,r2)));
return;
}
int c1=x<<1;
int c2=x<<1|1;
if (max(l1+S1[c1],l2+S2[c1])<max(r1+S1[c2],r2+S2[c2]))
solve(c2,l1+S1[c1],r1,l2+S2[c1],r2);
else
solve(c1,l1,r1+S1[c2],l2,r2+S2[c2]);
}

int main()
{
freopen("plane.in","r",stdin);
freopen("plane.out","w",stdout);
read(N); for (MAXN=1;MAXN<N;MAXN<<=1);
MAXN--;
for (int i=0;i<N;i++)
read(A[i].first),read(A[i].second);
sort(A,A+N);
int xp=0,lx=-1;
for (int i=0;i<N;i++)
{
if (A[i].first!=lx)
lx=A[i].first,xp++;
A[i].first=xp;
}
sort(A,A+N,cmp);
for (int i=0;i<N;i++)
update(S1,A[i].first,1);
ans=N;
for (int i=0;i<N;)
{
int sz=0;
while (i+sz<N && A[i].second==A[i+sz].second)
{
update(S1,A[i+sz].first,-1);
update(S2,A[i+sz].first,1);
sz++;
}
solve(1,0,0,0,0);
i+=sz;
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: