zoukankan      html  css  js  c++  java
  • 【刷题】【单调栈】请客

    神奇做法,神奇算法

    #include<cstdio>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    using namespace std;
    int n,m;
    const int N=303;
    int d[N][N],mn[N],f[N];
    int ans[N*N];
    
    stack <int > s;
    void calc()
    {
        int sum;
        for(int i=1;i<=n;i++)
        {
            sum=1,f[i]=1;//初始化 
            while(!s.empty() && mn[s.top() ] > mn[i] )//然后从这一行向上扩展 
            {
                f[i]+=f[s.top() ];
                ans[mn[s.top() ] ]+=f[s.top() ]*sum;
                
                sum+=f[s.top() ];
                s.pop() ;
            }
            s.push(i); 
        }
        sum=1;
        while(!s.empty() )
        {
            ans[mn[s.top() ] ]+=f[s.top() ]*sum;
            sum+=f[s.top() ];
            s.pop() ;
        }
    }
    
    int main()
    {
        //input
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&d[i][j]);
        //work
        for(int i=1;i<=m;i++)//枚举左端点
        {
            for(int j=1;j<=n;j++) mn[j]=d[j][i];
            calc();
            
            for(int j=i+1;j<=m;j++)//枚举右端点 
            {
                for(int k=1;k<=n;k++)
                    mn[k]=min(mn[k],d[k][j]);//一行一行的得到mn值  
                calc();//求左右端点之间,以各行结尾的矩形数 
            }
        }
        //output
        int mx=n*m;
        for(int i=1;i<=mx;i++) printf("%d
    ",ans[i]);
        return 0;
    } 
  • 相关阅读:
    推箱子
    去掉两个最高分、去掉两个最低分,求平均分
    投票选班长
    彩票
    闰年、平年
    闹钟
    手机号抽奖
    for练习--侦察兵
    兔子、棋盘放粮食、猴子吃桃
    for练习--凑法
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11837459.html
Copyright © 2011-2022 走看看