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
线段树套按秩合并 并查集: