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 }
原文地址:https://www.cnblogs.com/war1111/p/7709735.html