第一:二分的判断。
可以看到:在W取0时,所有的区间内的矿石都可以选上,
而在W大于最大的质量时,所有的矿石都选不上。
然后简单算一下就发现:
W越大,矿石选的越少,W越小,矿石选的越多。
所以,随着W增大,Y值减小;
所以:二分的判断条件出来了:
当Y>s时,需要增大W来减小Y,从而|Y-s|变小;
当Y==s时,|Y-s|==0;
当Y<s时,需要减小W来增大Y,从而|Y-s|变大;
第二:前缀和。
我们在计算一个区间的和时(虽然这里是两个区间和再相乘,但没关系)
通常是用前缀和的方法来缩减时间,直接模拟是n*n的,而前缀和成了2*n
很显然:
在w[i]>=Ww[i]>=W时这个i矿石会在统计里(若<W就不管它了直接pre[i]=pre[i-1]),
矿石价值和是:pre_v[i]=pre_v[i-1]+v[i],前面的和加上当前这一个i矿石;
矿石数量和是:pre_n[i]=pre_n[i-1]+1,数量加1嘛。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll w[200010],v[200010],pre_w[200010],pre_v[200010];
ll l[200010],r[200010];
ll n;
//处理前缀和
void pre(ll W){
for(int i=1;i<=n;i++){
if(w[i]>=W){
pre_w[i]=pre_w[i-1]+1;
pre_v[i]=pre_v[i-1]+v[i];
}
else {
pre_w[i]=pre_w[i-1];
pre_v[i]=pre_v[i-1];
}
}
}
int main(){
ll m,s,W=0;
scanf("%lld %lld %lld",&n,&m,&s);
for(int i=1;i<=n;i++){
scanf("%lld %lld",&w[i],&v[i]);
W=max(W,w[i]);
}
for(int i=1;i<=m;i++){
scanf("%lld %lld",l+i,r+i);
}
ll low=0,high=W+1;
ll minn=0x3f3f3f3f3f3f3f3f;//这里必须是8个3f,,long long 的无穷大
while(low<=high){
W=(low+high+1)>>1;
ll y=0;
//前缀和
pre(W);
//累加yi;
for(int i=1;i<=m;i++){
y+=((pre_w[r[i]]-pre_w[l[i]-1])*(pre_v[r[i]]-pre_v[l[i]-1]));
}
//y==s直接得出最小值
if(y==s){
minn=0;
break;
}
if(y<s){
high=W-1;///w和y变化是成负相关的
}
else low=W+1;
minn=min(minn,abs(y-s));
memset(pre_w,0,sizeof(pre_w));
memset(pre_v,0,sizeof(pre_v));
}
printf("%lld\n",minn);
//cout<<minn<<endl;
return 0;
}
// /\ | / |**、
// / \ | / | \
// / \ |/ | / _____ ____ | /
// /------\ |\ |__/ / \ \ /\ / / \ | /
// / \ | \ | / \ \ / \ / /______\ |/
// / \ | \ | \ / \ / \ / \ |
// / \ | \ | \_____/ \/ \/ \_____ |
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//