• 【UOJ#196】【BZOJ4574】[Zjoi2016]线段树


    题目链接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4574

    http://uoj.ac/problem/196


    考虑数字随机并且值域够大,我们将元素离散化并且不需要去重。

    令$g[i]$表示每一个位置的期望大小。

    那么${Ans=sum (g[i]*(frac{n(n+1))}{2})^{q})}$

    考虑根据这个${(frac{n(n+1))}{2})^{q}}$转换一下问题,是不是可以变成:

    ---------------------------------------------分割线----------------------------------------------------------------

    令${sum[i][j]}$表示序列的第$i$个位置的元素在$q$次操作后变成了离散化之后$j$大的方案数。

    那么${Ans=sum_{i=1}^{n}sum _{j=1}^{n}(sum[i][j]*X[j])}$    //$X[i]$表示第离散化之后的第$i$个元素原本对应的数字的大小。


    ---------------------------------------------分割线----------------------------------------------------------------

    考虑如何求${sum}$数组。

    从左至右枚举离散化数列每一位上的值(设我枚举的数字为第${E}$大),我们知道一个数至多能够影响到一个有限的区间,即区间${[L,R]}$中每一个数字都没有它大。

    令${DP[k][i][j]}$表示第$k$次操作之后区间${[i,j]}$的值都小于等于当前枚举值的方案数。

    转移:

    ${DP[k][i][j]=sum _{u=L}^{i-1}(DP[k-1][u][j]*(u-1))+sum _{v=j+1}^{R}(DP[k-1][i][v]*(n-v))+DP[k-1][i][j]*(cnt[i-1]+cnt[j-i+1]+cnt[n-j])}$

    那么为啥是这样呢?

    我来尝试解释一下第一项即${sum _{u=L}^{i-1}(DP[k-1][u][j]*(u-1))}$

      这个转移其实是从区间${[U,j]}$转移到区间${[i,j]}$,拿为啥要乘上一个系数$(u-1)$,是因为我要使得${[u,i-1]}$这段区间内不再小于等于当前枚举的值。所以只要选取了${[1,u-1]}$这段区间内的一个元素作为操作的左端点,固定右端点为${i-1}$则一定会存在一个数字(因为第${L-1}$个数一定大于当前枚举的数)使得${[u,i-1]}$这个区间的数不再小于等于当前枚举的数。

    第二项的理解和第一项基本相同。

    第三项就比较简单了,如果我选取的区间不跨过第$i$个位置或第$j$个位置,那就不会产生状态的改变,可与之间从区间${[i,j]}$向区间${[i,j]}$转移

     

    对于每一个枚举的数字就算出了$DP$数组,我为了方便统计答案再设一个数组${sum{}'}$表示序列的第$i$个位置的元素在$q$次操作后变成了离散化之后数小于等于$j$大数的方案数。

    ${sum{}'[i][E]=sum{}'[i][E]+sum _{u=L}^{R-1}sum _{v=u+1}^{R}DP[q][u][v]}$

    最后在利用${sum{}'}$数组计算出${sum}$数组。

    ${Ans=sum_{i=1}^{n}sum _{j=1}^{n}(sum[i][j]*X[j])}$

    参考:http://blog.csdn.net/qq_34637390/article/details/51290087


      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<cstdlib>
      6 #include<cmath>
      7 #include<cstring>
      8 using namespace std;
      9 #define maxn 410
     10 #define llg long long 
     11 #define md (llg)((1e9)+7)
     12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
     13 #define DD(i,j,k) dp[(i)%2][j][k]//方便滚动数组优化空间  
     14 llg n,m,q,x[maxn],rank[maxn],L,R,wz[maxn];
     15 llg cnt[maxn],dp[2][maxn][maxn],sum[maxn][maxn],A[maxn][maxn];
     16 
     17 inline bool cmp(llg a,llg b) {return x[a]<x[b];}
     18 
     19 void init()
     20 {
     21     cin>>n>>q;
     22     for (llg i=1;i<=n;i++) scanf("%lld",&x[i]);
     23     for (llg i=1;i<=n;i++) wz[i]=i;
     24     sort(wz+1,wz+n+1,cmp);
     25     for (llg i=1;i<=n;i++) rank[wz[i]]=i;//第i个元素是第rank[i]小的
     26     //离散化
     27     for (llg i=1;i<=n;i++) cnt[i]=(i*i+i)/2;
     28     for(int i=1;i<=n;i++)for(int j=i;j<=n;j++)A[i][j]=cnt[i-1]+cnt[n-j]+cnt[j-i+1];
     29 }
     30 
     31 void DP(llg now)
     32 {
     33     for (llg i=L;i<=R;i++) for (llg j=L;j<=R;j++) DD(0,i,j)=DD(1,i,j)=0;
     34     DD(0,L,R)=1;
     35     llg val;
     36     for (llg k=1;k<=q;k++)
     37     {
     38         for (llg i=L;i<=R;i++)
     39         {
     40             val=0;
     41             for(int j=R;j>=i;j--)
     42             {
     43                 DD(k,i,j)=val; val=(val+DD(k-1,i,j)*(n-j))%md;//计算第二项
     44             }
     45         }
     46         for (llg j=L;j<=R;j++)
     47         {
     48             val=0;
     49             for(llg i=L;i<=j;i++)
     50             {
     51                 DD(k,i,j)=(DD(k,i,j)+val)%md; val=(val+DD(k-1,i,j)*(i-1));//计算第一项
     52             }
     53         }
     54         for (llg i=L;i<=R;i++)
     55         {
     56             for (llg j=i;j<=R;j++)
     57             {
     58                 DD(k,i,j)=(DD(k,i,j)+(DD(k-1,i,j)*A[i][j]))%md;//计算第三项
     59             }
     60         }
     61     }
     62     for (llg i=L;i<=R;i++)
     63     {
     64         val=0;
     65         for (llg j=R;j>=i;j--)
     66         {
     67             val+=DD(q,i,j); val%=md;
     68             sum[j][rank[now]]+=val;
     69             sum[j][rank[now]]%=md;
     70         }
     71     }
     72 }
     73 
     74 int main()
     75 {
     76     //yyj("seg");
     77     init();
     78     for (llg i=1;i<=n;i++)
     79     {
     80         L=R=i;
     81         while (L && x[L]<=x[i]) L--; L++;
     82         while (R<=n && x[R]<=x[i]) R++; R--;
     83         //预处理第i个元素可以影响的区间
     84         DP(i);
     85     }
     86 
     87     llg ans=0;
     88     for (llg i=1;i<=n;i++)
     89     {
     90         ans=0;
     91         for (llg j=1;j<=n;j++)
     92         {
     93             if (sum[i][j]==0) continue;
     94             for (llg k=1;k<j;k++) sum[i][j]-=sum[i][k];
     95             while (sum[i][j]<0) sum[i][j]+=md; 
     96             ans+=x[wz[j]]*sum[i][j]; ans%=md;
     97         }
     98         while (ans<0) ans+=md;
     99         printf("%lld",ans);
    100         if (i!=0) printf(" ");
    101     }
    102     return 0;
    103 }
    本文作者:xrdog 作者博客:http://www.cnblogs.com/Dragon-Light/ 转载请注明出处,侵权必究,保留最终解释权!
  • 相关阅读:
    html页面,左边点击链接,右边显示内容参考代码。
    下拉列表,鼠标移动上去改变颜色
    js生成验证码
    SAP MM模块之批次管理
    SAP 通过屏幕字段查看透明表
    SAP SD你要知道的透明表
    ]sap透明表、结构、簇介绍以及查找表方法
    设计模式(策略模式)
    设计模式(状态模式)
    设计模式(观察者模式)
  • 原文地址:https://www.cnblogs.com/Dragon-Light/p/6475923.html
Copyright © 2020-2023  润新知