HNOI模擬題 物理

2021-07-04 17:17:40 字數 2930 閱讀 6633

給出一維座標系上的n個點,和n個點所代表的區間,其中第乙個點座標為0。對於任意兩個點,右邊的點可以到達左邊(包括座標相同)當且僅當滿足它們代表的區間有重合且距離不超過乙個給出的值l。求編號2——n的點到第乙個點的最短距離。無法到達輸出-1

對於50%的資料,3≤n≤20000;

對於100%的資料,1≤n≤250000,0≤xi,yi,li≤2000000000,1≤l≤2000000000,xi≤yi

在1右邊的點到達1,也相當於從1出發到其它的點。所以跑個單源最短路是可行的,但是資料範圍較大,加上兩點連邊的數量也可能很大,所以最短路會超時。

這道題時間限制比較寬,所以o(n^2)的單源最短路是可以過掉的。對當前的點列舉其它點,判斷區間是否重合即可。因為兩點之間的距離為1,我們可以直接打個bfs,設di

s[i]

為1到i的最短距離,轉移方程顯然

n達到250000的情況,bfs會超時。這時我們考慮用資料結構來維護區間。

那麼我們可以給區間以li為關鍵字排序,然後進行插入、查詢、刪除。

考慮兩個問題:

1. 如何用資料結構插入並查詢區間;

2. 如何用資料結構刪除乙個區間;

如果列舉的區間的座標是從小到大的,那麼顯然,它們的答案也是不遞減的,所以對於線段樹的每個節點都開個單調佇列來維護最小值,刪除時直接刪掉隊首。

對於乙個

1..n l

..r ,區間l.

.r最多會被分成lo

g(n)

塊。所以單調對列的總大小不會太大。

考慮乙個實現上的問題。如何插入區間能使與它有重合的區間查詢到它。

當插入操作到達乙個線段樹的區間l.

.r時,如果這lo

g(n)

個區間是l.

.r的乙個子區間,我們也把它放進單調佇列。

查詢的時候,對於這lo

g(n)

log(n

) 個區間的乙個子區間,插入的時候,我們到了這lo

g(n)

個區間就退出了,那麼可能會查詢不到。

其實這個問題只要與上面相反地,對於乙個插入區間的lo

g(n)

個塊,我們開另乙個單調佇列,專門記錄這些插入區間,當查詢操作到達乙個線段樹區間l.

.r,如果這lo

g(n)

個區間是l.

.r的乙個子區間,我們就在這個單調佇列裡查詢,就不會有遺漏了。

時間複雜度是o(

nlog

2n) 的

下面附一下**(不夠優美別介意o(∩_∩)o)

#include 

#include

#include

#define maxn 250005

#define maxm 1048585

#define maxs 26250205

#define inf 2000000005

#define hd head[id]

#define tl tail[id]

#define b_id b[i].id

using namespace std;

int n,l,m,p,tot,ans[maxn],interval[maxn][2],place[maxn];

struct data

a[maxn*2] , b[maxn*2] ;

bool cmp (data a , data b)

struct monotone_queue

void insert ( int

id , int x )

void delete ( int

id , int x )

int query ( int

id )

} data1 , data2 ;

void insert (int l , int r , int a , int b , int

id , int x)

int mid= (l + r) / 2;

if (b <= mid) insert(l , mid , a , b , id , x * 2);

else

if (a > mid) insert(mid+1 , r , a , b , id , x * 2 + 1);

else

}void delete (int l , int r , int a , int b , int

id , int x)

int mid= (l + r) / 2;

if (b <= mid) delete(l , mid , a , b , id , x * 2);

else

if (a > mid) delete(mid+1 , r , a , b , id , x * 2 + 1);

else

}int query (int l , int r , int a , int b , int x)

void init ()

sort (a , a+m , cmp);

p = 0;

for (int i=0 ; i < m ; i++) interval[ a[i].id ] [ a[i].typ ] = (!i || a[i].x != a[i-1].x )? ++p : p;

tot = 0;

for (int i = 1 ; i < n ; i++)

b[tot].x = 0; b[tot].id = 0; b[tot++].typ = 1;

sort (b , b+tot , cmp);

}void work ()

else

for (int i = 1 ; i < n ; i++)

if ( ans[i] <= n ) printf("%d\n",ans[i]); else printf("-1\n");

}int main ()

作業系統(模擬題,HNOI2003)

用優先佇列維護等待程序,同時用兩個變數分別維護當前時間和當前程序。每當乙個新程序到來時,看看再其到來之前,又有哪些程序執行完畢。然後再與當前優先順序最高的程序比較優先順序,進行簡單的分類討論。最後不要忘記,所有程序都進來之後,再將他們從優先佇列中彈出,直到優先隊列為空為止。include inclu...

實時物理模擬

物理模擬入門的大致方向。大致有 1 剛體 rigidbody 的模擬,學習的書籍有多剛體動力學,建議看國外的書籍,國內書籍看了後距離 仍還有相當大距離,開源的專案有bullet等。也可參看以下面的 2 柔體 1 小變形,使用有限元 fem finite element methods 工程上常用。機...

CG物理模擬 風箏模擬

放風箏是一項起源於中國的傳統娛樂專案,隨後推廣到世界各地。按作用可以分成節日慶典祝福風箏,體育競技類,單純的娛樂向風箏等。要想用計算機較為真實的模擬風箏運動,首先我們先得搞清楚風箏的受力情況。飛行原理 如圖 b 所示,風箏在天空中飛翔時所受的力為 風箏線的張力,尾巴的張力,自身的重力,以及風的作用力...