A All-one Matrices

题意,求子矩阵内有多少个全1的子矩阵,且每个1是被其对应的最大的一个子矩阵包含。

做法:

单调栈处理所有合法矩阵,然后去重即可

n*mlog(n*m)是会超时的,去重只能用线性的方法去重,这里比较活的是用了一个栈去重,很妙

由于一个细节没写好,老是wa

【代码】

#include<bits/stdc++.h>
using namespace std;
const int N=3e3+10;
int L[N][N],R[N][N];
char s[N][N];
int n,m,up[N][N],sum[N][N],sta[N],top=0;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s[i]+1);
        for(int j=1;j<=m;++j)
        {
            if(s[i][j]=='1') up[i][j]=1;
            sum[i][j]=sum[i][j-1]+up[i][j];
        }
    }
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)
    if(s[i][j]=='1') up[i][j]+=up[i-1][j];//预处理高度
    for(int i=1;i<=n;++i)//处理左端点
    {
        top=0;
        sta[0]=0;
        for(int j=1;j<=m;++j)
        {
            if(s[i][j]=='0')
            {
                L[i][j]=-1;
                top=0;sta[top]=j;continue;
            }
            while(top>=1&&up[i][j]<=up[i][sta[top]]) --top;
            L[i][j]=sta[top]+1;
            sta[++top]=j;
        }
    }
    for(int i=1;i<=n;++i)//处理右端点
    {
        top=0;sta[0]=m+1;
        for(int j=m;j>=1;--j)
        {
            if(s[i][j]=='0')
            {
                R[i][j]=-1;
                top=0;sta[top]=j;continue;
            }
            while(top>=1&&up[i][j]<=up[i][sta[top]]) --top;
            R[i][j]=sta[top]-1;
            sta[++top]=j;
        }
    }
    int ans=0;
    for(int i=1;i<=n;++i)
    {
        top=0;
        for(int j=1;j<=m;++j)
        {
            if(up[i][j]==0)
            {
                top=0;
                continue;
            }
            while(top>=1&&up[i][sta[top]]>up[i][j]) --top;
            if(top==0||up[i][sta[top]]!=up[i][j])
            {
                sta[++top]=j;
                int l=L[i][j],r=R[i][j];
                if(sum[i+1][r]-sum[i+1][l-1]!=r-l+1)
                {
                    ans++;
                }
            }
        }
    }
    printf("%d\n",ans);
}

B Beauty Values

签到题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int G[N];
int a[N];

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    ll ans=0;
    for(int i=1;i<=n;++i)  G[i]=0;
    for(int i=1;i<=n;++i)
    {
       ans+=1ll*(i-G[a[i]])*(n-i+1);
        G[a[i]]=i;
    }
    printf("%lld\n",ans);
}

C CDMA

极其复杂的构造题

具体构造方法就是

2 的答案 是 1 1

                    1 -1

4的答案就是1 1 1 1

                     1 -1 1 -1

                     1 1   -1 -1

                      1 -1  -1 1

每次扩展的时候((3,1)~(4,2))(((1,3)~(2,4)矩阵是跟((1,1)~(2,2))是一样的

而((3,3)~(4,4))矩阵是((1,1)~(2,2)都加了一个负号

【代码】

#include<bits/stdc++.h>
using namespace std;
const int N=2e3+10;
int a[N][N];
int main()
{
    int n;
    cin>>n;
    int t=1,num=0;
    for(;t<n;++t)
    {
        num++;
        t=t*2;
    }
    t=2;
    a[1][1]=1;
    a[1][2]=1;
    a[2][1]=1;
    a[2][2]=-1;
    int st=1;
    while(st<num)
    {
        for(int i=1;i<=t;i++)
        {
            for(int j=1;j<=t;j++)
            {
                int r1=j+t;
                a[i][r1]=a[i][j];
                a[i+t][j]=a[i][j];
                a[i+t][j+t]=-a[i][j];
            }
        }
        t=t*2;st++;
    }
    for(int i=1;i<=t;++i)
    {
        for(int j=1;j<=t;++j) printf("%d ",a[i][j]);
        puts("");
    }
}

G Gemstones

签到题

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+7;
string s;
char ch[N];
int Ans=0,top=0;
int main(){
    cin>>s;
    for(int i=0;i<s.length();i++){
        ch[++top]=s[i];
        while(top>=3&&ch[top]==ch[top-1]&&ch[top]==ch[top-2]){
            top-=3;
            Ans++;
        }
    }
    printf("%d\n",Ans);
}

2019.9.21 补题:

E -Explorer 

线段树套按秩合并 并查集:

javascript:void(0)