1. 程式人生 > >「PKUSC2018」星際穿越 (70分做法)

「PKUSC2018」星際穿越 (70分做法)

期望 成功 習慣 ons 由於 nbsp inpu 開始 long long

5371: [Pkusc2018]星際穿越

Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 27 Solved: 11
[Submit][Status][Discuss]

Description

有n個星球,它們的編號是1到n,它們坐落在同一個星系內,這個星系可以抽象為一條數軸,每個星球都是數軸上的一個點, 特別地,編號為i的星球的坐標是i。 一開始,由於科技上的原因,這n個星球的居民之間無法進行交流,因此他們也不知道彼此的存在。 現在,這些星球獨立發展出了星際穿越與星際交流的工具。 對於第i個星球,他通過發射強力信號,成功地與編號在[Li,i-1]的所有星球取得了聯系(編號為1的星球沒有發出任何信號), 取得聯系的兩個星球會建立雙向的傳送門,對於建立了傳送門的兩個星球u,v,u上的居民可以花費1單位時間傳送到v, v上的居民也可以花費1單位時間傳送到u,我們用dist(x,y)表示從編號為x的星球出發,通過一系列星球間的傳送門, 傳送到編號為y的星球最少需要花費的時間。 現在有q個星際商人,第i個商人初始所在的位置是xi,他的目的地是[Li,Ri]中的其中一個星球,保證Li<Ri<xi。 他會在這些星球中等概率挑選一個星球y(每個星球都有一樣的概率被選中作為目的地), 然後通過一系列星球的傳送門,花費最少的時間到達星球y。 商人想知道他花費的期望時間是多少?也就是計算∑dist(xi,y)/(Ri-Li+1),其中y<=Li<=Ri

Input

第一行一個正整數n,表示星球的個數。 第二行n-1個正整數,第i個正整數為Li+1, 表示編號在[Li+1,i]區間內所有星球已經與編號為i+1的星球取得了聯系,並且可以通過花費1單位進行彼此的傳輸。保證Li+1≤i 第三行一個正整數q,表示詢問組數。 接下來q行,每行三個數字Li,Ri,xi,表示在[Li,Ri]這個區間中等概率選擇一個星球y,dist(xi,y)的期望。 保證Li<Ri<xi,n,q≤3×10^5

Output

對於每組詢問,註意到答案必然是一個有理數,因此以p/q的格式輸出這個有理數,要求gcd(p,q)=1 如果答案為整數m,輸出m/1

Sample Input

7
1 1 2 1 4 6
5
3 4 6
1 5 7
1 2 4
1 2 6
1 3 5

Sample Output

3/2
13/5
3/2
2/1
1/1
我本沒有什麽平時做題也寫暴力的習慣,只是填一下考場上的坑罷了。。。。 pkusc day2的時候一開始就去懟T3計算幾何,雖然思路和正解一樣但無奈寫掛了2333,最後剩2h給T1和T2,暴力都沒打全,GG。 所以就有T1大眾分70我45的奇特景觀。。。。。。 70分的話,只需要發現最優策略只能最多向右走一步(並且是第一步),所以我們可以 O(N^2) 掃一遍,預處理出來一個數組 f[i][j] 表示 點i走j步能走到左端最遠的那個點,然後用這個更新一下dis[i][j](兩兩點之間的最短路),做一個前綴和,直接回答詢問即可。。。。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5005;

int mn[maxn],L[maxn],n,Q,f[maxn][maxn],d[maxn][maxn],a,b,c;

int gcd(int x,int y){ return y?gcd(y,x%y):x;}

inline void prework(){
	mn[n+1]=n+1;
	for(int i=n;i;i--) mn[i]=min(mn[i+1],L[i]);
	
	for(int i=1;i<=n;i++) f[i][2]=mn[i+1],f[i][0]=i,f[i][1]=L[i];
	
	for(int i=2,k,j;i<=n;i++){
		k=i-1;
		
	    for(j=1;f[i][j]>1;j++)
	        for(;k>=f[i][j];k--) f[i][j+1]=min(f[i][j+1],L[k]),d[i][k]=j;
	    
	    for(;k;k--) d[i][k]=j;
	}
	
	for(int i=2;i<=n;i++)
	    for(int j=1;j<i;j++) d[i][j]+=d[i][j-1]; 
}

inline void solve(){
	scanf("%d",&Q);
	while(Q--){
		scanf("%d%d%d",&a,&b,&c);
		c=d[c][b]-d[c][a-1];
		a=b-a+1,b=gcd(a,c);
		a/=b,c/=b;
		
		printf("%d/%d\n",c,a);
	}
}

int main(){
	memset(f,0x3f,sizeof(f));
	
	scanf("%d",&n),L[1]=1;
	for(int i=2;i<=n;i++) scanf("%d",L+i);
	
	prework();
	solve();
	
	return 0;
}

「PKUSC2018」星際穿越 (70分做法)