题目链接:https://ac.nowcoder.com/acm/problem/217803
思路:首先考虑如何求出所有的得分情况,可以发现每个p[i]对应的a[p[i]] 是肯定会出现的
而将p[i] 排序后 每段p[i] p[i+1] 中的最大值也是会出现的, 其他都不会出现, 那么这里就考虑用RMQ或者线段树求一下区间的最大值
然后考虑如何计算得分概率,对应每一个数 可以预处理他左边能达到的地方和右边能达到的最远的地方,记作l[i] r[i]
用单调栈可以o n 处理出来 然后剩下的就是维护 每次查询的时候 左边和右边都有多少个可选的 相乘*2 ,如果自己本身的位置也可选就减1
最后在gcd 化简分数即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=998244353; 5 #define ll long long 6 #define pi pair<ll,ll> 7 #define fi first 8 #define sc second 9 #define pb push_back 10 int a[maxn],pos[maxn],p[maxn]; 11 int n,m,k; 12 int l[maxn],r[maxn]; 13 int tr[maxn]; 14 pi b[maxn]; 15 16 ll gcd(ll a,ll b) 17 { 18 if(b==0) return a; 19 return gcd(b,a%b); 20 } 21 22 void add(int x,int v) 23 { 24 while(x<=n) tr[x]+=v,x+=x&-x; 25 } 26 int query(int x) 27 { 28 int ans=0; 29 while(x) ans+=tr[x],x-=x&-x; 30 return ans; 31 } 32 33 struct ac 34 { 35 int l,r,mx; 36 }; 37 ac tree[maxn*4]; 38 void pushup(int x) 39 { 40 tree[x].mx=max(tree[x<<1].mx,tree[x<<1|1].mx); 41 } 42 void build(int x,int l,int r) 43 { 44 tree[x]={l,r}; 45 if(l==r) 46 { 47 tree[x].mx=a[l]; 48 return; 49 } 50 int mid=(l+r)/2; 51 build(x<<1,l,mid); 52 build(x<<1|1,mid+1,r); 53 pushup(x); 54 } 55 int querymx(int x,int l,int r) 56 { 57 if(l>r) return 0; 58 int L=tree[x].l,R=tree[x].r; 59 if(l<=L&&R<=r) return tree[x].mx; 60 int mid=(L+R)/2; 61 int ans=0; 62 if(l<=mid) ans=querymx(x<<1,l,r); 63 if(r>mid) ans=max(ans,querymx(x<<1|1,l,r)); 64 return ans; 65 } 66 67 68 69 70 int main() 71 { 72 ios::sync_with_stdio(0); 73 cin.tie(0); 74 cin>>n; 75 for(int i=1;i<=n;i++) cin>>a[i],pos[a[i]]=i; 76 stack<int>s; 77 for(int i=1;i<=n;i++) 78 { 79 int x=a[i]; 80 while(!s.empty()&&x>a[s.top()]) s.pop(); 81 if(s.empty()) l[i]=1; 82 else l[i]=s.top()+1; 83 s.push(i); 84 } 85 while(!s.empty()) s.pop(); 86 for(int i=n;i>=1;i--) 87 { 88 int x=a[i]; 89 while(!s.empty()&&x>a[s.top()]) s.pop(); 90 if(s.empty()) r[i]=n; 91 else r[i]=s.top()-1; 92 s.push(i); 93 } 94 build(1,1,n); 95 cin>>m; 96 while(m--) 97 { 98 int k; 99 cin>>k; 100 for(int i=1;i<=k;i++) cin>>p[i]; 101 sort(p+1,p+1+k); 102 vector<int>cnt; 103 for(int i=1;i<=k;i++) 104 { 105 int x=a[p[i]],y=querymx(1,p[i],p[i+1]); 106 if(i!=k) cnt.pb(y); 107 cnt.pb(x); 108 } 109 sort(cnt.begin(),cnt.end()); 110 cnt.erase(unique(cnt.begin(),cnt.end()),cnt.end()); 111 for(int i=1;i<=k;i++) add(p[i],1); 112 int tot=0; 113 114 for(auto &v:cnt) 115 { 116 ll mu=1ll*k*k; 117 int pp=pos[v]; 118 ll L=query(pp)-query(l[pp]-1); 119 ll R=query(r[pp])-query(pp-1); 120 ll zi=L*R*2; 121 if(query(pp)-query(pp-1)) zi--; 122 ll d=gcd(zi,mu); 123 zi/=d,mu/=d; 124 b[++tot]={zi,mu}; 125 } 126 for(int i=1;i<=tot;i++) 127 { 128 cout<<cnt[i-1]<<" "<<b[i].fi<<"/"<<b[i].sc<<'\n'; 129 } 130 131 for(int i=1;i<=k;i++) add(p[i],-1); 132 133 } 134 135 136 137 138 139 140 141 142 143 }View Code