首
先
求
出
每
个
人
分
到
0
个
写
标
程
,
1
个
写
标
程
,
2
个
写
标
程
.
.
.
的
时
间
都
拿
出
来
排
个
序
。
然
后
考
虑
一
个
时
间
区
间
[
l
,
r
]
,
要
求
所
有
人
都
在
这
个
时
间
内
完
成
。
那
么
对
于
每
个
人
写
标
程
的
个
数
一
定
是
一
个
区
间
[
L
i
,
R
i
]
内
。
其
实
我
们
只
要
t
w
o
p
o
i
n
t
e
r
扫
一
下
,
然
后
记
一
下
每
个
人
的
L
i
和
R
i
的
值
就
做
完
了
,
因
为
这
是
区
间
,
所
以
很
好
维
护
。
首先求出每个人分到0个写标程, 1个写标程, 2个写标程...的时间都拿出来排个序。 然后考虑一个时间区间[l,r],要求所有人都在这个时间内完成。 那么对于每个人写标程的个数一定是一个区间[Li,Ri]内。 其实我们只要two pointer扫一下,然后记一下每个人的L_i和R_i的值就做完了,因为这是区间,所以很好维护。
首先求出每个人分到0个写标程,1个写标程,2个写标程...的时间都拿出来排个序。然后考虑一个时间区间[l,r],要求所有人都在这个时间内完成。那么对于每个人写标程的个数一定是一个区间[Li,Ri]内。其实我们只要twopointer扫一下,然后记一下每个人的Li和Ri的值就做完了,因为这是区间,所以很好维护。
双指针也就是二级指针,二级指针是相对一级指针而言的。二级指针一般用于函数参数传递;
一开始没想到该怎么贪心,就凉了
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
int id,c;
ll v;
}p[400010];
int n,m,x,y,cnt,tot,a[400010],b[400010],has[400010],l,r;
ll ans=2e18;
bool cmp(node a,node b)
{
return a.v<b.v;
}
int main(){
cin>>x>>y>>n;
m=(x+y)/n;
for(int i=1;i<=n;++i)
{
scanf("%d%d",&a[i],&b[i]);
for(int j=0;j<=m;++j)
p[++cnt]={i,j,1ll*a[i]*j+1ll*b[i]*(m-j)};
}
sort(p+1,p+cnt+1,cmp);
for(int i=1,j=1;i<=cnt;i++)
{
while(j<=cnt&&(tot<n||l>x||r<x))
{
int tmp=p[j].id;
if(!has[tmp])
l+=p[j].c,r+=p[j].c,++tot;
else if(a[tmp]<=b[tmp])
--l;
else
++r;
++has[tmp];
j++;
}
if(tot==n)
ans=min(ans,p[j-1].v-p[i].v);
int tmp=p[i].id;
if(has[tmp]==1)
l-=p[i].c,r-=p[i].c,--tot;
else if(a[tmp]<=b[tmp])
++l;
else
--r;
--has[tmp];
}
cout<<ans;
}
来源:zr