Description
New Orleans家的后院有很多片草坪,Sullivan负责清理过高的草。但是,Sullivan还有很多家务要干,于是,她想到了一个好方法。
后院总共有n片草坪,第i片草坪投影到数轴上,是一段l[i]到r[i]的闭区间,保证l[i]+r[i]是偶数,l[i]<=r[i]。
Sullivan可以在整点上放0v0来把草吃掉(于是0v0变成了0π0)。如果第i片草坪覆盖了x点上的0π0(l[i]<=x<=r[i]),那么这只0π0就可以吃掉这片草坪里的草。每一片草坪的草需要且只能被一只0π0吃掉。如果一片草坪覆盖了多只0π0,Sullivan可以选择任意一只去吃草。
但是,0π0吃草是有代价的,对于第i片草坪,假如吃草的0π0位于x点上,代价为abs((x-l[i])-(r[i]-x)),即0π0到草坪两端距离之差。
现在,Sullivan想知道:
1.最少需要放几只0v0?
2.在放最少只数的0v0情况下,代价最小是多少?
Input
第一行两个正整数n,t。
第二行到第n+1行,第i+1行两个正整数l[i],r[i]。
Output
第一行一个非负整数,为最小的0v0数量。
如果t=0,没有第二行输出;如果t=1,第二行输出在放最少只数的0v0情况的最小代价。
Sample Input
3 1
1 11
2 4
5 7
Sample Output
2
0
Data Constraint
20% n,l[i],r[i]<=3000 t=0
30% n,l[i],r[i]<=300000 t=0
20% n,l[i],r[i]<=3000 t=1
30% n,l[i],r[i]<=300000 t=1
Solution
第一问显然
第二问呢?
设f[i]表示到i这个位置而且i必须放,包含了1~i区间的最优答案
区间压成一个点,压到区间中点,这里包含区间就指包含区间中点
那么对于每个i,可以通过一个j转移过来,同时j要合法
转移时答案增加一些数
对于区间在j~i的,偏向j的与j匹配,否则与i匹配
即将j~i的中点分开,两边的区间分别向两边匹配
就这么做事
O(n2)
的
好像有什么决策单调性??
有大佬知道教我一些
反正数据水,
O(n2)
就可以过了
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(ll i=a;i<=b;i++)
#define fd(i,a,b) for(ll i=a;i>=b;i--)
#define N 301000
#define ll long long
using namespace std;
ll n,t,m,p[N],f[N],s1[N],s2[N],g[N],ans=214748364745751ll;
struct node{
ll x,y,z;
}a[N];
bool cnt(node x,node y){return x.z<y.z;}
ll get(ll l,ll r,ll x)
{
l--;
if(x==r) return (s1[r]-s1[l])*x-(s2[r]-s2[l]);
else return (s2[r]-s2[l])-(s1[r]-s1[l])*x;
}
int main()
{
freopen("grass.in","r",stdin);
freopen("grass.out","w",stdout);
scanf("%lld%lld",&n,&t);
fo(i,1,n) scanf("%lld%lld",&a[i].x,&a[i].y),a[i].z=(a[i].x+a[i].y)/2,m=max(m,a[i].y);
sort(a+1,a+n+1,cnt);
memset(g,60,sizeof(g));
memset(f,60,sizeof(f));
memset(p,0,sizeof(p));
fo(i,1,n) s1[a[i].z]++,s2[a[i].z]+=a[i].z,p[a[i].y+1]=max(p[a[i].y+1],a[i].x);
fo(i,1,m+1) s1[i]+=s1[i-1],s2[i]+=s2[i-1],p[i]=max(p[i-1],p[i]);
g[0]=f[0]=0;
fo(i,1,m)
{
fo(j,p[i],i-1)
{
if(g[j]+1>g[i]) break;
g[i]=g[j]+1;
f[i]=min(f[i],f[j]+get(j,(i+j)/2,j)+get((i+j)/2+1,i,i));
}
}
fo(i,p[m+1],m) ans=min(ans,g[i]);
printf("%lld\n",ans);
if(!t) return 0;
ll jy=ans;ans=214748364745751ll;
fo(i,p[m+1],m) if(g[i]==jy) ans=min(ans,f[i]+get(i,m,i));
printf("%lld\n",ans*2ll);
}