hdu 6052 To my boyfriend
2017-07-28 14:24
531 查看
题目
OvO click here http://acm.hdu.edu.cn/showproblem.php?pid=6052
(2017 Multi-University Training Contest - Team 2 - 1008)
解
分开考虑每种颜色
pre[i][j]代表第j列最近一个i颜色的行数,ppre是次近
calcu(li,ji,x,y,clr)表示从col=li到col=ri,计算(x,y)点对mp[x][y]=clr颜色有贡献的矩形的个数(其实并不是,准确说是(n-i+1)*(calcu(1,m,i,j,mp[i][j])-calcu(1,j-1,i,j,mp[i][j])-calcu(j+1,m,i,j,mp[i][j]))才是有贡献的矩形的个数)
记每个子矩阵中,对于每种颜色,记最上(同层则最左)的那个点对该矩阵该颜色有贡献.
接下来然后搜索每个点,对于每个点用单调栈计算合法矩阵个数,对于点(i,j)就是前文提过的(n-i+1)*(calcu(1,m,i,j,mp[i][j])-calcu(1,j-1,i,j,mp[i][j])-calcu(j+1,m,i,j,mp[i][j]))
calcu函数中,对于每个扫到的列,如果它的高度小于当前栈顶的高度,那么把栈顶的元素弹出来,并且把宽度加到当前这个列中。因为栈中超出当前列的高度的那部分已经不会再对矩形个数产生贡献。
calcu中tmp的作用其实就是能产生贡献的方块的左上角的坐标个数
(本思路来自某其他博客)
OvO click here http://acm.hdu.edu.cn/showproblem.php?pid=6052
(2017 Multi-University Training Contest - Team 2 - 1008)
解
分开考虑每种颜色
pre[i][j]代表第j列最近一个i颜色的行数,ppre是次近
calcu(li,ji,x,y,clr)表示从col=li到col=ri,计算(x,y)点对mp[x][y]=clr颜色有贡献的矩形的个数(其实并不是,准确说是(n-i+1)*(calcu(1,m,i,j,mp[i][j])-calcu(1,j-1,i,j,mp[i][j])-calcu(j+1,m,i,j,mp[i][j]))才是有贡献的矩形的个数)
记每个子矩阵中,对于每种颜色,记最上(同层则最左)的那个点对该矩阵该颜色有贡献.
接下来然后搜索每个点,对于每个点用单调栈计算合法矩阵个数,对于点(i,j)就是前文提过的(n-i+1)*(calcu(1,m,i,j,mp[i][j])-calcu(1,j-1,i,j,mp[i][j])-calcu(j+1,m,i,j,mp[i][j]))
calcu函数中,对于每个扫到的列,如果它的高度小于当前栈顶的高度,那么把栈顶的元素弹出来,并且把宽度加到当前这个列中。因为栈中超出当前列的高度的那部分已经不会再对矩形个数产生贡献。
calcu中tmp的作用其实就是能产生贡献的方块的左上角的坐标个数
(本思路来自某其他博客)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const ll M=124; struct node { ll h,x; } stk[M]; ll n,m; ll mp[M][M]; ll pre[M*M][M],ppre[M*M][M]; //i,j the row of color=i, in col=j ll lstk; double ans; void init() { ans=0; memset(pre,0,sizeof(pre)); memset(ppre,0,sizeof(ppre)); } //calcu the num of appropriate matrix whose buttom is row x, from col li to col ri, ll calcu(ll li,ll ri,ll x,ll y,ll clr) { node p; ll k,tmp=0; ll ret=0; lstk=0; for(k=li;k<=ri;k++) { if(pre[clr][k]==x && k>=y) p.h=x-ppre[clr][k]; else p.h=x-pre[clr][k]; p.x=1; if(p.h==0) { tmp=0; lstk=0; continue; } while(lstk>0 && stk[lstk].h>p.h) { tmp-=stk[lstk].h*stk[lstk].x; p.x+=stk[lstk--].x; } stk[++lstk]=p; tmp+=p.h*p.x; ret+=tmp; } return ret; } void solve() { ll i,j; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { ppre[mp[i][j]][j]=pre[mp[i][j]][j]; pre[mp[i][j]][j]=i; } for(j=1;j<=m;j++) ans+=1ll*(n-i+1)*(calcu(1,m,i,j,mp[i][j])-calcu(1,j-1,i,j,mp[i][j])-calcu(j+1,m,i,j,mp[i][j])); } ans=ans*4/(1ll*n*m*(n+1)*(m+1)); printf("%.9lf\n",ans); } int main() { ll i,j,T; cin>>T; while(T--) { scanf("%lld%lld",&n,&m); for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%lld",&mp[i][j]); init(); solve(); } return 0; }
相关文章推荐
- HDU 6052 To my boyfriend 思维 + 枚举(计数)
- HDU-6052 To my boyfriend 思维
- HDU 6052 To my boyfriend(容斥+单调栈)
- HDU-6052 To my boyfriend 思维
- HDU 6052 To my boyfriend(悬线法)
- HDU 6052 To my boyfriend 期望 计数
- HDU-6052 To my boyfriend 思维
- 17暑假多校联赛2.8 HDU 6052 To my boyfriend
- HDU 6052 To my boyfriend
- HDU-6052 To my boyfriend 思维
- HDU-6052 To my boyfriend 思维
- (2017多校训练第二场)HDU - 6052 To my boyfriend 思维题
- HDU-6052 To my boyfriend 思维
- hdu 6052 To my boyfriend
- HDU-6052 To my boyfriend 思维
- 第二场 hdu 6052 To my boyfriend
- HDU 6052 To my boyfriend【思维】
- Hdu-6052 To my boyfriend(单调栈)
- HDU-6052 To my boyfriend 思维
- HDU-6052 To my boyfriend 思维