奶牛集会
Description
约翰家的N头奶牛每年都会参加“哞哞大会” 。哞哞大会是世界奶牛界的盛事。集会上 的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等。当然,哞哞大叫肯定也包括在内。 奶牛们的叫声很大,很多奶牛在参加多年活动之后,实际上已经失去了一部分的听力。
奶牛们已经站在了一条直线上,i号奶牛的坐标为Xi,她只能听到大于Vi的声音。每头奶 牛的位置坐标都是唯一的。
如果i号和j号奶牛想对话,则他们使用的音量为max {Vi, Vj} × |Xi −Xj|
N头奶牛可以组合成N(N − 1)/2对奶牛,假设每对奶牛都使用最小的音量在对话,请计 算所有奶牛产生的总音量是多少。
Input Format
第一行:单个整数:N,1 ≤ N ≤ 20000
第二行到第N + 1行:每行有两个用空格分开的整数,Vi和Xi,1 ≤ Vi ≤ 20000, 1 ≤ Xi ≤ 20000
Output Format
第一行:单个整数,表示最小音量之和
----------------------------------------------------------
正解=线段树(其实用树状数组也可以)
注意到max{vi,vj}中,显然只有大的才有贡献
将 vi 从小到大排序一一进树:
设当前做到 i
先统计当前线段树中比xi大的个数num1及和sum1,ans+=vi*(sum1-num1*xi)
再统计当前线段树中比xi小的个数num2及和sum2,ans+=vi*(num2*xi-sum2)
将 xi 插入线段树
Ps.好像很都存在两个相对大小变量的题,按其中一个变量排序后,题目都会变得很愉悦~
代码如下:
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<string> 5 #include<iostream> 6 #define INF 9999999 7 #define LL long long 8 using namespace std; 9 struct Point{ 10 int x; 11 long long v; 12 }a[20001]; 13 bool cmp(const Point&X,const Point&Y){ 14 return X.v<Y.v; 15 } 16 int Min=INF,Max=-INF; 17 int L,R,o,n; 18 long long sum[200000],num[200000]; 19 long long now,ans; 20 long long query(int root,int l,int r){ 21 if(!num[root]) return 0; 22 if(L<=l&&r<=R) 23 return sum[root]-num[root]*now; 24 int mid=(l+r)>>1; 25 long long t=0; 26 if(mid>=L) t+=query(root<<1 ,l ,mid); 27 if(mid<R) t+=query(root<<1|1,mid+1,r); 28 return t; 29 } 30 void insert(int root,int l,int r,int p){ 31 sum[root]+=p; 32 num[root]++; 33 if(l==r) return ; 34 int mid=(l+r)>>1; 35 if(mid>=p) insert(root<<1,l,mid,p); 36 else insert(root<<1|1,mid+1,r,p); 37 } 38 int main(){ 39 scanf("%d",&n); 40 for(int i=1;i<=n;i++){ 41 scanf("%lld%d",&a[i].v,&a[i].x); 42 Min=min(a[i].x,Min); 43 Max=max(a[i].x,Max); 44 } 45 sort(a+1,a+1+n,cmp); 46 LL T=0; 47 for(int i=1;i<=n;i++){ 48 now=a[i].x; 49 L=a[i].x ; R=Max; 50 ans+=a[i].v*query(1,Min,Max); 51 L=Min ; R=a[i].x; 52 ans-=a[i].v*query(1,Min,Max); 53 insert(1,Min,Max,a[i].x); 54 } 55 printf("%lld",ans); 56 }
-----------------------------------------------------------------------------------
奶牛抗议
Description
约翰家的N头奶牛聚集在一起,排成一列,正在进行一项抗议活动。第i头奶牛的理智度 为Ai,Ai可能是负数。约翰希望奶牛在抗议时保持理性,为此,他打算将所有的奶牛隔离成 若干个小组,每个小组内的奶牛的理智度总和都要大于零。由于奶牛是按直线排列的,所以 一个小组内的奶牛位置必须是连续的。
请帮助约翰计算一下,存在多少种不同的分组的方案。由于答案可能很大,只要输出答 案除以1,000,000,009的余数即可。
Input Format
第一行:单个整数:N,1 ≤ N ≤ 10^6
第二行到N + 1行:在第i + 1行有一个整数:Ai,表示第i头奶牛的理智度,−10^5 ≤ Ai ≤ 10^5
Output Format
第一行:单个整数,表示分组方案数除以1,000,000,009的余数
--------------------------------------------------------------------------------------------------
正解=离散化+树状数组,
和上一题有异曲同工之妙~
设f[i] 为到第 i 只奶牛有几种分组,
设sum[i]为奶牛的前缀和
显然 f[i]= ∑f[j](sum[i]-sum[j]>=0)