1. 程式人生 > >P2345 奶牛集會andP2657 低頭一族

P2345 奶牛集會andP2657 低頭一族

分別是 指標 one src 歸並 algorithm 交流 背景 algo

做法是一樣的

技術分享
題目背景

MooFest, 2004 Open

題目描述

約翰的N 頭奶牛每年都會參加“哞哞大會”。哞哞大會是奶牛界的盛事。集會上的活動很

多,比如堆幹草,跨柵欄,摸牛仔的屁股等等。它們參加活動時會聚在一起,第i 頭奶牛的坐標為Xi,沒有兩頭奶牛的坐標是相同的。奶牛們的叫聲很大,第i 頭和第j 頭奶牛交流,會發出max{Vi; Vj}×|Xi ? Xj | 的音量,其中Vi 和Vj 分別是第i 頭和第j 頭奶牛的聽力。假設每對奶牛之間同時都在說話,請計算所有奶牛產生的音量之和是多少。

輸入輸出格式

輸入格式:
? 第一行:單個整數N,1 ≤ N ≤ 20000

? 第二行到第N 
+ 1 行:第i + 1 行有兩個整數Vi 和Xi,1 ≤ Vi ≤ 20000; 1 ≤ Xi ≤ 20000 輸出格式: ? 單個整數:表示所有奶牛產生的音量之和 輸入輸出樣例 輸入樣例#14 3 1 2 5 2 6 4 3 輸出樣例#157 說明 樸素O(N2) 類似於歸並排序的二分O(N logN) 樹狀數組O(N logN)
V奶牛的集會 技術分享
題目描述

一群青年人排成一隊,用手機互相聊天。

每個人的手機有一個信號接收指標,第i個人的接收指標設為v[i]。

如果位置在x[i]的人要和位置在xj的人聊天,那麽這兩人組成的一對的信號發射強度就是abs(x[i]-x[j])*max(v[i],v[j]).

現在我們想知道,這些人所有對子中的信號發射強度的總和。

輸入輸出格式

輸入格式:
第一行一個整數N,接下來N行,每行兩個整數v[i]和x[i]。

輸出格式:
所有對的信號發射強度總和。

輸入輸出樣例

輸入樣例#
14 3 1 2 5 2 6 4 3 輸出樣例#157 說明 對於40%的數據,N<=5,000 對於100%的數據,N<=100,000 1≤x[i]≤20,000 [color=red]註意:可能有兩人在同一個位置 答案在int64或long long範圍內[/color]
低頭一族

 思路: 

  先按照V排一下序只考慮X就行了,因為對於V大的來說,他和別人的貢獻只是X的差得和。(這個用lowbit維護)。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include
<math.h> #include<cmath> using namespace std; typedef long long LL; int n; LL num[20010],tot[20010]; struct node{ int x; int v; }a[100009]; int lowbit(int x) {return x&(-x);} bool cmp(node a,node b) { return a.v<b.v; } long long ans; int MAX; void Add(LL *C,int x,int y) { while(x<=MAX) { C[x]+=y; x+=lowbit(x); } } LL query(LL *C,int x) { LL res=0; while(x>0) { res+=C[x]; x-=lowbit(x); } return res; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].v,&a[i].x),MAX=max(MAX,a[i].x); sort(a+1,a+1+n,cmp); for(int i=1,x,v;i<=n;i++) { x=a[i].x,v=a[i].v; LL totl,totr,numl,numr; numl=query(num,x-1);totl=query(tot,x-1); numr=query(num,MAX)-query(num,x);totr=query(tot,MAX)-query(tot,x); ans+=v*(totr-totl+x*numl-x*numr); Add(num,x,1); Add(tot,x,x); } cout<<ans; return 0; }

P2345 奶牛集會andP2657 低頭一族