zoukankan      html  css  js  c++  java
  • 「PKUSC2018」星际穿越 (70分做法)

    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
    ",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;
    }
    
  • 相关阅读:
    如何设计一个秒杀系统
    Leetcode题目437:路径总和III(递归-简单)
    Leetcode题目461:汉明距离(位运算-简单)
    Leetcode题目617:合并二叉树(递归-简单)
    分布式锁
    分布式搜索引擎
    数据库
    Java知识体系思维导图
    wav文件头详解,看懂wav文件
    推荐一个最近在学习的AI算法工程师手册,侵删
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9190149.html
Copyright © 2011-2022 走看看