第一:二分的判斷。
可以看到:在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
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//