vijos1740 聪明的质监员 (二分、区间求和)
http://www.rqnoj.cn/problem/657
|
|
大意:给你一排物品,有重量wi,价值vi,再给你一排区间。有一个W,对每个区间求Σ1*Σvi,两个Σ都是符合w[j]>=W的j,也就是若一个区间里有3个物品的w大于等于W,则这个区间的值为3*(w1+w2+w3)。要使各区间的这个值的和与给定值S的绝对值最小,求这个最小的绝对值。
题解:二分+区间求和。
因为各区间值的和随W单调递减,可以二分W。每次二分都要怒求好多区间的区间和,所以我们每次二分,都求一次根据这个W生成的前缀和,方便求区间和。
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usint unsigned int 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(int i=0;i<(n);i++) 18 #define FOR(i,x,n) for(int i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 26 const int maxn=222222; 27 int w[maxn],v[maxn]; 28 int L[maxn],R[maxn]; 29 int n,m; 30 ll S; 31 32 ll ss[maxn],cn[maxn]; 33 34 void check(ll a[],int n){ 35 for(int i=0;i<n;i++) 36 printf("%5lld ",a[i]); 37 puts(""); 38 } 39 40 ll gank(int W) { 41 ll re=0; 42 ss[0]=0; 43 cn[0]=0; 44 for(int i=1; i<=n; i++) { 45 if(w[i-1]>=W) { 46 ss[i]=ss[i-1]+v[i-1]; 47 cn[i]=cn[i-1]+1; 48 } else { 49 ss[i]=ss[i-1]; 50 cn[i]=cn[i-1]; 51 } 52 } 53 for(int i=0; i<m; i++) { 54 re+=(cn[R[i]]-cn[L[i]-1])*(ss[R[i]]-ss[L[i]-1]); 55 // cout<<cn[R[i]]-cn[L[i]-1]<<'*'<<ss[R[i]]-ss[L[i]-1]<<endl; 56 } 57 // check(ss,n+1); 58 // check(cn,n+1); 59 // printf("↑W=%d,re=%lld\n",W,re); 60 return re; 61 } 62 63 int main() { 64 int i,j,l,r,mid,maxr; 65 while(scanf("%d%d%lld",&n,&m,&S)!=EOF) { 66 maxr=0; 67 REP(i,n) { 68 scanf("%d%d",&w[i],&v[i]); 69 maxr=max(maxr,w[i]+1); 70 } 71 REP(i,m) { 72 scanf("%d%d",&L[i],&R[i]); 73 //L[i]--; 74 //R[i]--; 75 } 76 l=1; 77 r=maxr; 78 while(l<=r) { 79 mid=(l+r)>>1; 80 if(S>gank(mid)) r=mid-1; 81 else l=mid+1; 82 } 83 //cout<<mid<<','<<l<<','<<r<<endl; 84 ll t=abs(S-gank(mid)); 85 t=min(t,abs(S-gank(l))); 86 t=min(t,abs(S-gank(r))); 87 printf("%lld\n",t); 88 } 89 return 0; 90 }

浙公网安备 33010602011771号