zoukankan      html  css  js  c++  java
  • 模拟104 题解

    A. 中间值

    二分答案在数组$a$中的排名,则得到期望的在数组$b$中的排名。

    当数组$b$中对应的数恰好是大于二分值的第一个数,代表二分到了答案。

    通过对应的数与当前数的大小关系,可以确定二分方向。

    同理还应当二分答案在数组$b$中的排名。

    然而这个做法实现比较困难,还有另一个更帅的二分做法。

    考虑当前的问题:

    数组$a$,单调区间$[l_1,r_1]$,数组$b$,单调区间$[l_2,r_2]$,查询共同区间的第$k$大值。

    不妨将$k$折半,分别对应在$a$,$b$数组中,

    可以得到$a_{r_1-frac{k}{2}}$,$b_{r_2-frac{k}{2}}$。

    将二者比较可以确定一段无用的区间。

    设$a_{r_1-frac{k}{2}}<b_{r_2-frac{k}{2}}$,$b$数组在大于$r_2-frac{k}{2}$的部分只会更大。

    所以问题的规模降低了一半,变为了问题

    数组$a$,单调区间$[l_1,r_1]$,数组$b$,单调区间$[l_2,r_2-frac{k}{2}]$,查询共同区间的第$frac{k}{2}$大值。

    所以可以$O(logn)$处理每组询问。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int N=5e5+7;
     5 const int inf=0x3f3f3f3f;
     6 int n,m;
     7 int a[N],b[N];
     8 inline int query(int l1,int r1,int l2,int r2){
     9     int l,r,lst,nxt,ans=-1,len1=r1-l1+1,len2=r2-l2+1,aim=len1+len2+1>>1;
    10     lst=b[l2-1]; nxt=b[r2+1];
    11     b[l2-1]=-1; b[r2+1]=inf;
    12     l=l1; r=r1;
    13     while(l<=r){
    14         int mid=l+r>>1,rk=mid-l1+1,to=aim-rk+l2;//大于 的第一个
    15         if(to<l2){
    16             r=mid-1;
    17             continue;
    18         }
    19         if(to>r2+1){
    20             l=mid+1;
    21             continue;
    22         }
    23         if(b[to]>=a[mid]&&b[to-1]<=a[mid]){
    24             ans=a[mid];
    25             break;
    26         }
    27         if(l==r) break;
    28         if(b[to-1]>a[mid]) l=mid+1;
    29         else r=mid-1;
    30     }
    31     b[l2-1]=lst; b[r2+1]=nxt;
    32     if(~ans) return ans;
    33     lst=a[l1-1]; nxt=a[r1+1];
    34     a[l1-1]=-1; a[r1+1]=inf;
    35     l=l2; r=r2;
    36     while(l<=r){
    37         int mid=l+r>>1,rk=mid-l2+1,to=aim-rk+l1;
    38         if(to<l1){
    39             r=mid-1;
    40             continue;
    41         }
    42         if(to>r1+1){
    43             l=mid+1;
    44             continue;
    45         }
    46         if(a[to]>=b[mid]&&a[to-1]<=b[mid]){
    47             ans=b[mid];
    48             break;
    49         }
    50         if(a[to-1]>b[mid]) l=mid+1;
    51         else r=mid-1;
    52     }
    53     a[l1-1]=lst; a[r1+1]=nxt;
    54     if(~ans) return ans;
    55     return 0;
    56 }
    57 inline int read(register int x=0,register char ch=getchar(),register char f=0){
    58     for(;!isdigit(ch);ch=getchar()) f=ch=='-';
    59     for(; isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
    60     return f?-x:x;
    61 }
    62 int main(){
    63     freopen("median.in","r",stdin);
    64     freopen("median.out","w",stdout);
    65     n=read(); m=read(); a[0]=b[0]=-1; a[n+1]=b[n+1]=inf;
    66     for(int i=1;i<=n;++i) a[i]=read();
    67     for(int i=1;i<=n;++i) b[i]=read();
    68     for(int i=1,opt,l1,r1,l2,r2;i<=m;++i){
    69         opt=read();
    70         if(opt==1){
    71             l1=read(); r1=read(); l2=read();
    72             if(l1==0) a[r1]=l2;
    73             else b[r1]=l2;
    74         }
    75         else{
    76             l1=read(); r1=read(); l2=read(); r2=read();
    77             printf("%d
    ",query(l1,r1,l2,r2));
    78         }
    79     }
    80     return 0;
    81 }
    解法一
     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int N=5e5+7;
     5 const int inf=0x3f3f3f3f;
     6 int n,m;
     7 int a[N],b[N];
     8 int solve(int st1,int ed1,int st2,int ed2,int k){
     9     if(k==1){
    10         if(st1<=ed1&&st2<=ed2) return max(a[ed1],b[ed2]);
    11         return st1<=ed1?a[ed1]:b[ed2];
    12     }
    13     int x=k>>1,y=k-x,to1=ed1-x,to2=ed2-y;
    14     if(to1<st1-1) return solve(st1,ed1,st2,to2,k-y);
    15     if(to2<st2-1) return solve(st1,to1,st2,ed2,k-x);
    16     if(a[to1+1]>=b[to2+1]) return solve(st1,to1,st2,ed2,k-x);
    17     return solve(st1,ed1,st2,to2,k-y);
    18 }
    19 inline int read(register int x=0,register char ch=getchar(),register char f=0){
    20     for(;!isdigit(ch);ch=getchar()) f=ch=='-';
    21     for(; isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
    22     return f?-x:x;
    23 }
    24 int main(){
    25     freopen("median.in","r",stdin);
    26     freopen("median.out","w",stdout);
    27     n=read(); m=read();
    28     for(int i=1;i<=n;++i) a[i]=read();
    29     for(int i=1;i<=n;++i) b[i]=read();
    30     for(int i=1,opt,l1,r1,l2,r2;i<=m;++i){
    31         opt=read();
    32         if(opt==1){
    33             l1=read(); r1=read(); l2=read();
    34             if(l1==0) a[r1]=l2;
    35             else b[r1]=l2;
    36         }
    37         else{
    38             l1=read(); r1=read(); l2=read(); r2=read();
    39             printf("%d
    ",solve(l1,r1,l2,r2,r2+r1-l1-l2+3>>1));
    40         }
    41     }
    42     return 0;
    43 }
    解法二

    B. 最小值

    首先写出弱智$dp$。

    $dp_i$表示以$i$为结尾的几段区间的最优决策下的答案。

    $dp_i=dp_{j-1}+f(min_{k=j}^i a_k)$。

    这个东西只与两点间的最值有关,所以单调栈维护最值的决策区间,

    顺便线段树维护一下$dp$的最优决策就完了。

    C. 最大值

    首先是一个整数期望公式。

    $x$为一个随机变量,那么

    $E(x)=sum limits_{i=1}^{inf}P(x==i)*i$

    $E(x)=sum limits_{i=1}^{inf}P(x==i)sum limits_{j=1}^{i}$

    改变枚举顺序,有

    $E(x)=sum limits_{i=1}^{inf}P(x>=i)$

    应当注意到,本题中每组询问是独立互不影响的,

    也就是说可以分别统计每组询问的答案,之后简单求和。

    求单组询问的期望,枚举$i$,问题是求$P(max_{j=l}^{r}v_j)>=i)$

    $=1-Pi_{j=l}^{r}P(v_j<x)$

    $=1-Pi_{j=l}^{r}1-P(v_j>=x)$

    对于一个点,$P(v_j>=x)$是容易求出的。

    题中的特殊性质是,不存在区间包含的情况,

    所以对所有区间按左端点排序,包含一个点的区间是连续的。

    对于相邻两个$x$,可以将答案简单的除原概率,乘上新的概率。

    注意到本题中的$P(v_j>=x)$是单调的,只要倒序枚举$x$,就可以有效避免除$0$的情况。

    对所有的询问建树,问题转化为区间乘法(当然还有通过乘逆元进行的除法),顺便维护整体的和就可以了。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #define lch p<<1
      7 #define rch p<<1|1
      8 #define ll long long
      9 using namespace std;
     10 const int mod=1e9+7;
     11 const int N=2e5+7;
     12 int n,m,q,cnt;
     13 int lsh[N],L[N],R[N];
     14 vector<pair<int,ll> > ve[N],f[N];
     15 inline int read(register int x=0,register char ch=getchar(),register char f=0){
     16     for(;!isdigit(ch);ch=getchar()) f=ch=='-';
     17     for(; isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
     18     return f?-x:x;
     19 }
     20 inline ll qpow(ll x,int k,ll r=1){
     21     for(;k;k>>=1,x=x*x%mod) if(k&1) r=r*x%mod;
     22     return r;
     23 }
     24 struct Query{
     25     int l,r;
     26 }que[N];
     27 struct node{
     28     int l,r;
     29     ll val,lzy;
     30 }s[N<<2];
     31 void build(int p,int l,int r){
     32     s[p].l=l; s[p].r=r; s[p].lzy=1; s[p].val=r-l+1;
     33     if(l==r) return ;
     34     int mid=l+r>>1;
     35     build(lch,l,mid);
     36     build(rch,mid+1,r);
     37 }
     38 inline void down(int p){
     39     s[lch].val=s[p].lzy*s[lch].val%mod;
     40     s[rch].val=s[p].lzy*s[rch].val%mod;
     41     s[lch].lzy=s[p].lzy*s[lch].lzy%mod;
     42     s[rch].lzy=s[p].lzy*s[rch].lzy%mod;
     43     s[p].lzy=1;
     44 }
     45 void mult(int p,int l,int r,ll val){
     46     if(s[p].l>=l&&s[p].r<=r) return s[p].val=s[p].val*val%mod,s[p].lzy=s[p].lzy*val%mod,void();
     47     if(s[p].lzy!=1) down(p);
     48     if(l<=s[lch].r) mult(lch,l,r,val);
     49     if(r>=s[rch].l) mult(rch,l,r,val);
     50     s[p].val=(s[lch].val+s[rch].val)%mod;
     51 }
     52 int main(){
     53     freopen("max.in","r",stdin);
     54     freopen("max.out","w",stdout);
     55     n=read(); m=read(); q=read();
     56     for(int i=1,x,y,p;i<=m;++i){
     57         x=read(); y=read(); p=read(); lsh[++cnt]=y;
     58         ve[x].push_back(make_pair(y,p));
     59     }
     60     sort(lsh+1,lsh+cnt+1); cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
     61     for(int i=1;i<=n;++i){
     62         sort(ve[i].begin(),ve[i].end());
     63         for(int j=0;j<ve[i].size();++j) ve[i][j].first=lower_bound(lsh+1,lsh+cnt+1,ve[i][j].first)-lsh;
     64         for(int j=0;j<ve[i].size();++j){
     65             if(f[i].empty()||ve[i][j].first!=f[i].back().first) f[i].push_back(ve[i][j]);
     66             else f[i].back().second=((1-(1-f[i].back().second)*(1-ve[i][j].second))%mod+mod)%mod;
     67         }
     68         ve[i].clear();
     69         ll p=1,po=0;//前面一个都没出现的概率
     70         for(int j=0;j<f[i].size();++j){
     71             ll tmp=f[i][j].second;
     72             f[i][j].second=p*f[i][j].second%mod;
     73             p=p*(1-tmp+mod)%mod;
     74             po=(po+f[i][j].second)%mod;
     75         }
     76         f[i].push_back(make_pair(0,1-po+mod));
     77         sort(f[i].begin(),f[i].end());
     78         for(int j=f[i].size()-2;~j;--j) (f[i][j].second+=f[i][j+1].second)%=mod;
     79     }
     80     for(int i=1;i<=n;++i) for(int j=0;j<f[i].size();++j) ve[f[i][j].first].push_back(make_pair(i,j));
     81     for(int i=1;i<=n;++i) f[i].push_back(make_pair(cnt+1,0));
     82     ll ans=0;
     83     for(int i=1;i<=q;++i) que[i].l=read(),que[i].r=read();
     84     sort(que+1,que+q+1,[](const Query &x,const Query &y){return x.l<y.l;});
     85     L[0]=1; R[n+1]=q;
     86     for(int i=1;i<=n;++i){
     87         L[i]=L[i-1];
     88         while(L[i]<=q&&que[L[i]].r<i) ++L[i];
     89     }
     90     for(int i=n;i;--i){
     91         R[i]=R[i+1];
     92         while(R[i]&&que[R[i]].l>i) --R[i];
     93     }
     94     build(1,1,q);
     95     for(int i=cnt;i;--i){
     96         for(int j=0;j<ve[i].size();++j){
     97             int pos=ve[i][j].first;
     98             if(L[pos]>R[pos]) continue;
     99             mult(1,L[pos],R[pos],qpow(1-f[pos][ve[i][j].second+1].second+mod,mod-2));
    100             mult(1,L[pos],R[pos],1-f[pos][ve[i][j].second].second);
    101         }
    102         (ans+=(lsh[i]-lsh[i-1])*(q-s[1].val)%mod)%=mod;
    103     }
    104     printf("%lld
    ",(ans+mod)%mod);
    105     return 0;    
    106 }
    T3
  • 相关阅读:
    关于Visual Studio.NET 2008开发一册通C# 3.0从基础到项目实战的读后感
    书.NET 3.5与VB 2008高级编程(第3版)的评论
    Java 基础语法
    idea 无法创建子目录
    壁纸
    【博客园】美化
    Java变量和常量
    本人负责任的告诉你,从博客看不出什么东东来。
    DataFormating的用法总结
    javascript弹出div(一)
  • 原文地址:https://www.cnblogs.com/skyh/p/11815741.html
Copyright © 2011-2022 走看看