【HDOJ6305】RMQ Similar Sequence(笛卡尔树)
题意:
给定一个数组a,现在存在一个数组b,其元素值在[0,1]随机生成
若对于a,b,任意rmq问题的最值出现在同一个数组中的位置,则数组b的价值为∑b[i],否则为0,求数组b的期望价值
n<=1e6
思路:
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second 19 #define MP make_pair 20 21 int read() 22 { 23 int v=0,f=1; 24 char c=getchar(); 25 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 26 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 27 return v*f; 28 } 29 30 const ll MOD=1e9+7; 31 const int N=1100000; 32 33 int f[N][20],a[N],lg[N],cas,n; 34 ll ans; 35 ll inv[N]; 36 37 int query(int l,int r) 38 { 39 int len=r-l+1; 40 int q=lg[len]; 41 if (a[f[l][q]]>=a[f[r-(1<<q)+1][q]]) return f[l][q]; 42 else return f[r-(1<<q)+1][q]; 43 } 44 45 void solve(int l,int r) 46 { 47 ans=ans*inv[r-l+1]%MOD; 48 int mid=query(l,r); 49 if(l<mid) solve(l,mid-1); 50 if(mid<r) solve(mid+1,r); 51 } 52 53 int main() 54 { 55 freopen("1008.in","r",stdin); 56 freopen("1008.out","w",stdout); 57 cas=read(); 58 for(int i=2;i<=1000000;i++) lg[i]=lg[i>>1]+1; 59 inv[0]=inv[1]=1; 60 for(int i=2;i<=1000000;i++) inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD; 61 while(cas--) 62 { 63 n=read(); 64 for(int i=1;i<=n;i++) 65 { 66 a[i]=read(); 67 f[i][0]=i; 68 } 69 for(int i=1;i<=20;i++) 70 for(int j=1;j<=n-(1<<i)+1;j++) 71 if(a[f[j][i-1]]>=a[f[j+(1<<(i-1))][i-1]]) f[j][i]=f[j][i-1]; 72 else f[j][i]=f[j+(1<<(i-1))][i-1]; 73 ans=1; 74 solve(1,n); 75 ans=ans*inv[2]%MOD*n%MOD; 76 printf("%lld\n",ans); 77 } 78 return 0; 79 }
null