SY3-2-Queue

题目描述:

期末到了,N个学生准备去操场拍期末照。每个人有一个身高,排队结束后大家按顺序离开操场,每当一个人离开前就会拍一张照片。一张照片的奇怪程度定义为相邻的两个人的身高差平方之和。已知学生的身高和每个人的位置,按照读入顺序离开,你想知道照片奇怪值的期望值是多少。

答案用最简分数表示,若分母为1,则写成整数形式。

输入格式:

第一行一个N,表示人数

第二行N个正整数hi,按照离开操场顺序给出每一个学生的身高

第三行N个正整数pi,按照离开操场顺序给出每一个学生的位置

输出格式:

一行,一个分数,表示答案
样例输入:

3

6 5 8

2 1 3

样例输出:

14/3

数据范围:

2<=N<=500000, 1<=hi<=10000, 1<=pi<=N, 且若i≠j则pi≠pj

样例解释:

第一张照片为5 6 8,这张照片奇怪程度为5

位置2上的同学离开

第二张照片为5 8,这张照片奇怪程度为9

位置1上的同学离开

第二张照片为8,这张照片奇怪程度为0

————————————————————————————————————————————————
这道题因为有500万的数据,所以对数组进行排序是不现实的,因此在读入的时候就要一次到位,避免循环。
我们可以发现,每次拍完照片会有一个人出队,这时候如果他会有三种情况:
1.队首
2.队尾
3.队中
1和2是类似的情况,3是更加普遍的情况
对于情况3来说,设出队的人位置为i,其他的人的身高方差不变,减少了一个i-1与i的差平方,一个i,i+1的差平方,增加一个i-1,i+1的差平方。
我们可以维护一个初始情况下所有人的身高差平方差之和ans1,每次循环时将ans1进行如上所述的更新,并加入答案中。
在人出队以后需要将其去除,如果从数组中强行去除或者打上没了的标记时间复杂度会高,可以直接让i-1右边的位置变为i+1,i+1左边的位置变为i-1即可。
我们建立一个结构,含有三个成员:身高,左边的人的间隔,右边的人的间隔。
然后循环更新即可。

#include <stdio.h>  
#include <string.h>  
#include <math.h>  
#define ll unsigned long long  
struct node{  
    ll l, r, h;  
}a[500010];  
ll b[500010] = {0}, c[500010] = {0}, ans = 0, ans1 = 0;  
ll gcd (ll a, ll b) { return b == 0 ? a : gcd (b, a % b); }  
int main () {  
    int n;  
    scanf("%d", &n);  
    for (int i = 1; i <= n; i++) scanf("%llu", &b[i]);  
    for (int i = 1; i <= n; i++) {  
        ll m;   
        scanf("%llu", &m);  
        a[m].h = b[i];  
        a[m].l = a[m].r = 1;  
        c[i] = m;  
    }  
    //for (int i = 1; i <= n; i++) printf("%llu\n", a[i].h);  
    for (int i = 1; i < n; i++) ans += (a[i].h - a[i + 1].h) * (a[i].h - a[i + 1].h);  
    ans1 = ans;  
    for (int i = 1; i <= n; i++) {  
        if (c[i] - a[c[i]].l >= 1 && c[i] + a[c[i]].r <= n) {  
            ans1 -= (a[c[i]].h - a[c[i] - a[c[i]].l].h) * (a[c[i]].h - a[c[i] - a[c[i]].l].h);  
            ans1 -= (a[c[i]].h - a[c[i] + a[c[i]].r].h) * (a[c[i]].h - a[c[i] + a[c[i]].r].h);  
            ans1 += (a[c[i] + a[c[i]].r].h - a[c[i] - a[c[i]].l].h) * (a[c[i] + a[c[i]].r].h - a[c[i] - a[c[i]].l].h);  
            a[c[i] - a[c[i]].l].r = a[c[i] + a[c[i]].r].l = a[c[i]].l + a[c[i]].r;    
        }  
        else if (c[i] - a[c[i]].l < 1 && c[i] + a[c[i]].r <= n) {  
            ans1 -= (a[c[i]].h - a[c[i] + a[c[i]].r].h) * (a[c[i]].h - a[c[i] + a[c[i]].r].h);  
            a[c[i] + a[c[i]].r].l = a[c[i]].l + a[c[i]].r;    
        }  
        else if (c[i] - a[c[i]].l >= 1 && c[i] + a[c[i]].r > n) {  
            ans1 -= (a[c[i]].h - a[c[i] - a[c[i]].l].h) * (a[c[i]].h - a[c[i] - a[c[i]].l].h);  
            a[c[i] - a[c[i]].l].r = a[c[i]].l + a[c[i]].r;    
        }  
        ans += ans1;  
    }  
    if (ans % n == 0) printf("%llu\n", ans / n);  
    else printf("%llu/%llu\n", ans / gcd (ans, n), n / gcd (ans, n));  
    return 0;  
}  

posted @ 2022-05-31 20:01  misasteria  阅读(165)  评论(0编辑  收藏  举报