P3819 松江1843路
P3819 松江1843路
sigema(r[i]*abs(x[i]-x[s]));令它最小,是带权中位数问题,s是带权中位数,s左边的r[i]之和+r[s]大于s左边的r[i]之和,反过来也成立。如果sum+r[i]>=总数/2,就break,就找到带权中位数了。
证明的话去百度,很好证明,因为没有理解价值,就没整理。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #include<cmath> 6 #include<ctime> 7 #include<cstring> 8 #define inf 2147483647 9 #define For(i,a,b) for(register long long i=a;i<=b;i++) 10 #define p(a) putchar(a) 11 #define g() getchar() 12 //by war 13 //2017.10.22 14 using namespace std; 15 struct node 16 { 17 long long x; 18 long long r; 19 bool operator<(const node &aa)const 20 { 21 return x<aa.x; 22 } 23 }a[100010]; 24 long long n; 25 long long s; 26 long long L; 27 long long ans,sum; 28 void in(long long &x) 29 { 30 long long y=1; 31 char c=g();x=0; 32 while(c<'0'||c>'9') 33 { 34 if(c=='-') 35 y=-1; 36 c=g(); 37 } 38 while(c<='9'&&c>='0')x=x*10+c-'0',c=g(); 39 x*=y; 40 } 41 void o(long long x) 42 { 43 if(x<0) 44 { 45 p('-'); 46 x=-x; 47 } 48 if(x>9)o(x/10); 49 p(x%10+'0'); 50 } 51 int main() 52 { 53 in(L),in(n); 54 For(i,1,n) 55 in(a[i].x),in(a[i].r),s+=a[i].r; 56 sort(a+1,a+n+1); 57 s>>=1; 58 For(i,1,n) 59 { 60 sum+=a[i].r; 61 if(sum>=s) 62 { 63 s=i; 64 break; 65 } 66 } 67 For(i,1,n) 68 ans+=abs(a[s].x-a[i].x)*a[i].r; 69 o(ans); 70 return 0; 71 }