zoukankan      html  css  js  c++  java
  • Nowcoder9982A.牛牛和牛妹的RMQ(线段树+单调栈)

    链接:https://ac.nowcoder.com/acm/contest/9982/A
    来源:牛客网

    某天,牛妹来找牛牛学习RMQ算法(Range Minimum/Maximum Query),即区间最值查询。也就是给定一个数组区间[L,R],查询该子区间的最大值。
    假设子数组的两端点下标分别为L,R的话RMQ(L,R)就表示数组区间[L,R]的最大值。
    因为牛妹学会了RMQ算法,所以牛牛准备和她玩个游戏验证她真的学会了。

    牛牛有一个长度大小为n的全排列数组,即数组中的数字是1~n,且每个数字仅出现1次。
    她们一共玩了m轮游戏,在每轮游戏中,牛牛都准备了k个不同的下标。
    然后牛牛和牛妹各自随机选出一个下标,并且两人所选下标可以是相同的。
    假设牛牛选出的下标为a,牛妹选出的下标为b的话,那么本轮游戏的得分就是RMQ(min(a,b),max(a,b))。

    请你告诉牛牛,对于每轮游戏可能的得分都有哪几种情况,以及这些情况出现的概率各是多大?

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    int n,m;
    int a[maxn],p[maxn];
    struct node {
        int l,r,sum;
    }segTree[maxn<<2];
    void build (int i,int l,int r) {
        segTree[i].l=l;
        segTree[i].r=r;
        if (l==r) {
            segTree[i].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(i<<1,l,mid);
        build(i<<1|1,mid+1,r);
        segTree[i].sum=max(segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    int query (int i,int l,int r) {
        if (segTree[i].l>=l&&segTree[i].r<=r) return segTree[i].sum;
        int mid=(segTree[i].l+segTree[i].r)>>1;
        int ans=0;
        if (l<=mid) ans=max(ans,query(i<<1,l,r));
        if (r>mid) ans=max(ans,query(i<<1|1,l,r));
        return ans;
    }
    int pp[maxn],L[maxn],R[maxn];
    int main () {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",a+i);
        build(1,1,n);
        scanf("%d",&m);
        while (m--) {
            int k;
            scanf("%d",&k);
            for (int i=1;i<=k;i++) scanf("%d",p+i);
            sort(p+1,p+k+1);
            map<int,long long> mp;
            for (int i=1;i<k;i++) {
                int x=query(1,p[i],p[i+1]);
                pp[i]=x;
            }
            stack<int> st;
            for (int i=1;i<k;i++) R[i]=k,L[i]=0;
            for (int i=1;i<k;i++) {
                while (st.size()) {
                    int u=st.top();
                    if (pp[u]<=pp[i])
                        st.pop();
                    else {
                        L[i]=u;
                        break;
                    }
                }
                st.push(i);
            }
            while (st.size()) st.pop();
            for (int i=k-1;i>=1;i--) {
                while (st.size()) {
                    int u=st.top();
                    if (pp[u]<=pp[i])
                        st.pop();
                    else {
                        R[i]=u;
                        break;
                    }
                }
                st.push(i);
            }
            for (int i=1;i<k;i++) {
                int j;
                for (j=i;j<k;j++) if (pp[i]!=pp[j]) break;
                mp[pp[i]]+=2ll*(i-L[i]-1)*(R[j-1]-j);
                mp[pp[i]]+=1ll*(j-i+1)*(j-i);
                mp[pp[i]]+=2ll*(j-i)*(i-L[i]-1);
                mp[pp[i]]+=2ll*(j-i)*(R[j-1]-j);
                i=j-1; 
            }
            for (int i=1;i<=k;i++) mp[a[p[i]]]++;
            for (auto it=mp.begin();it!=mp.end();it++) {
                long long tt=it->second;
                long long x=1ll*k*k;
                long long gg=__gcd(tt,x);
                printf("%d %lld/%lld
    ",it->first,tt/gg,x/gg);
            }
        }
    }
  • 相关阅读:
    Windows8 Metro界面下的StreamSocket连接服务器
    使用CSS控制文字溢出
    Javascript中的恒等运算符与等于运算符的区别
    Sqlserver 中删除表数据的两种方式与区别
    Linux C++ 遇到的错误
    四、Vue Router 设置动态路由
    六、Vue Router 嵌套路由
    一、Vue Router 的使用
    三、Vuex Getter
    五、Vuex Action
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14369483.html
Copyright © 2011-2022 走看看