您的位置:首页 > 其它

Hdu-6052 To my boyfriend(单调栈)

2017-07-28 00:44 435 查看
Dear Liao I never forget the moment I met with you. You carefully asked me: "I have a very difficult problem. Can you teach me?". I replied with a smile, "of course". You replied:"Given a matrix, I randomly choose a sub-matrix, what is the expectation of the number of**different numbers** it contains?" Sincerely yours, GuoInputThe first line of input contains an integer T(T≤8) indicating the number of test cases. Each case contains two integers, n and m (1≤n, m≤100), the number of rows and the number of columns in the grid, respectively. The next n lines each contain m integers. In particular, the j-th integer in the i-th of these rows contains g_i,j (0≤ g_i,j < n*m).OutputEach case outputs a number that holds 9 decimal places.Sample Input
1
2 3
1 2 1
2 1 2
Sample Output
1.666666667
Hint
6(size = 1) + 14(size = 2) + 4(size = 3) + 4(size = 4) + 2(size = 6) = 30  / 18 = 6(size = 1) + 7(size = 2) + 2(size = 3) + 2(size = 4) + 1(size = 6)

分析:我们考虑计算每种颜色的贡献和,我们将某个子矩阵中对答案有贡献的方格定义为这个子矩阵的所有同色方格中最高上左的那个(先上后左),然后我们再转来计算每个方格贡献的子矩阵个数,这个用单调栈可以O(n)计算,总复杂度O(n^3).
#include <bits/stdc++.h>
#define N 105
using namespace std;
typedef long long ll;
struct thing
{
int x,n;
thing(){};
thing(int a,int b){x = a,n = b;}
}Stack
;
int T,n,m,tot,c

,pre[N*N]
,Pre[N*N]
,vis[N*N];
ll ans;
int Count(int l,int r,int i,int j,int col)
{
int sum = 0,t = 0,ans = 0;
for(int k = l;k <= r;k++)
{
int d = (i == pre[col][k] && k >= j) ?  i - Pre[col][k] : i - pre[col][k];
if(!d) t = sum = 0;
else
{
thing u = thing(d,1);
while(t && Stack[t].x >= u.x)
{
sum -= Stack[t].x*Stack[t].n;
u.n += Stack[t].n;
t--;
}
sum += u.x*u.n*1ll;
Stack[++t] = u;
ans += sum;
}
}
return ans;
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(pre,0,sizeof(pre));
memset(vis,0,sizeof(vis));
tot = 0,ans = 0;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++)
{
scanf("%d",&c[i][j]);
if(!vis[c[i][j]]) tot++,vis[c[i][j]] = 1;
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
Pre[c[i][j]][j] = pre[c[i][j]][j];
pre[c[i][j]][j] = i;
}
for(int j = 1;j <= m;j++)
{
int col = c[i][j];
ans += (n-i+1ll)*(Count(1,m,i,j,col) - Count(1,j-1,i,j,col) - Count(j+1,m,i,j,col));
}
}
printf("%.9f\n",ans*4.0/(n*(n+1)*m*(m+1)));
}
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: