http://media.hihocoder.com/contests/icpcbeijing2015/problems.pdf
题意:
将土地分成两份,土地上有绿洲,分土地有两个原则左边的绿洲大于等于右边的,使差距尽量小;左边的土地尽量的大
分析:
可以差分数组,也可以二分,暴力也行(数据有点水)
二分代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int x,y,w,h;
bool operator<(const node &aa)const
{
return x<aa.x;
}
}v[10005];
int n,r;
ll sum;
bool ok(int m)
{
int i,j;
long long ss;
ss=0;
for(i=0;i<n&&v[i].x<m;i++)
{
ss=ss+(ll)min(m-v[i].x,v[i].w)*v[i].h;
}
return ss>=sum-ss;
}
int main()
{
int t,i,j,rr;
scanf("%d",&t);
while(t--)
{
sum=0;
scanf("%d%d",&r,&n);
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&v[i].x,&v[i].y,&v[i].w,&v[i].h);
if(v[i].w+v[i].x>r)
v[i].w=r-v[i].x;
if(v[i].y-v[i].h<0)
v[i].h=v[i].y;
sum=sum+(ll)v[i].w*v[i].h;
}
sort(v,v+n);
int l=0,rr,mid,ans;
rr=r;
while(l<=r)
{
mid=(l+r)>>1;
if(ok(mid))
{
r=mid-1;
ans=mid;
}
else
l=mid+1;
}
bool flag;
l=ans;
int k;
flag=0;
v[n].x=rr;
for(i=0;i<=n;i++)
{
if(l>v[i].x&&l<v[i].x+v[i].w)
flag=1;
if(v[i].x>=l&&!flag){
flag=1;
l=v[i].x;
}
}
printf("%d\n",l);
}
}
差分代码:
#include<bits/stdc++.h>
using namespace std;
long long T,N,R,aa,bb,c,d,l,r,A,B;
long long a[1000010],b[1000010],all;
int lowbit(int i)
{
return i&(-i);
}
void add(int i,long long x)
{
long long t=i-1;
while(i<1000005)
{
a[i]+=x;
b[i]+=x*t;
i+=lowbit(i);
}
}
long long sum(int i)
{
long long s=0;
while(i>0)
{
s+=a[i];
i-=lowbit(i);
}
return s;
}
long long sum2(int i)
{
long long s=0;
while(i>0)
{
s+=b[i];
i-=lowbit(i);
}
return s;
}
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld",&R,&N);
all=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=N;i++)
{
scanf("%lld%lld%lld%lld",&aa,&bb,&c,&d);
l=min(R,aa+c);
r=max((long long)0,bb-d);
all+=(l-aa)*(bb-r);
add(aa+1,bb-r);
add(l+1,r-bb);
}
long long s,ss,bin=-1,ok;
for(int i=1;i<=R;i++)
{
A=i*sum(i);
B=sum2(i);
s=A-B;
ss=all-s;
if(s<ss) continue;
if(bin==-1) {bin=s;ok=i;}
else if(s>bin) break;
else ok=i;
}
printf("%lld\n",ok);
}
}
/*
5
1000
2
1 1 2 1
5 1 2 1
1000
1
1 1 2 1
*/