zoukankan      html  css  js  c++  java
  • 2020-3-21模拟赛题解

    T1

    直接模拟

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int main(){
        int x,y;
        cin>>x>>y;
        double ans;
        if(y==0){
            ans=10.0;
            if(x>3)ans+=1.0*(x-3.0)*2;
            if(x>15)ans+=1.0*(x-15.0);
        }else{
            ans=11.0;
            if(x>3)ans+=1.0*(x-3.0)*2;
            if(x>15)ans+=1.0*(x-15.0);
            ans+=(x-3)*0.4;
        }cout<<fixed<<setprecision(1)<<ans;
        return 0;
    }
    

    T2

    我们发现一场比赛

    • 如果分出了胜负,所有球队的积分和增加 33
    • 如果没分出胜负,所有球队的积分和增加 22

    所以,平局场数=比赛常数 × imes 3 - 所有球队的计分和

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int main(){
    	int n,t,s=0,x;
    	read(t);read(n);
    	for(int i=1;i<=t;i++){
    		read(x);
    		s+=x;//算和
    	}cout<<(3*n-s);//平局局数
    	return 0;
    }
    

    T3

    我傻,傻乎乎地写高精,只不过调得还满快的

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    string p,q,r;
    int x[1010],a[1010],b[1010];
    char work(int x){
    	if(x<=9)return char(x+48);
    	return char(x+55);
    }
    int work2(char x){
    	if(isdigit(x))return x-48;
    	return x-55;
    }
    string jf(string st1,string st2,int t){
    	memset(x,0,sizeof(x));
    	memset(a,0,sizeof(a));
    	memset(b,0,sizeof(b));
        string ans="";
        int k=-1,f=0,la,lb;
        for(int i=st1.size()-1;i>=0;i--){
            k++;
            a[k]=st1[i]-48;
        }la=st1.size();
        k=-1;
        for(int i=st2.size()-1;i>=0;i--){
            k++;
            b[k]=st2[i]-48;
        }lb=st2.size();
        for(int i=0;i<la;i++)
            for(int j=0;j<lb;j++)
                x[i+j]=x[i+j]+a[i]*b[j];
        for(int i=0;i<1000;i++){
            x[i+1]=x[i+1]+x[i]/t;
            x[i]=x[i]%t;
        }
        for(int i=1000;i>=0;i--)
            if(f)ans=ans+work(x[i]);
            else if(x[i]!=0){
                    ans=ans+work(x[i]);
                    f=1;
                }
        if(f==0)ans=ans+'0';
        return ans;
    }
    bool check(int x){
    	if(jf(p,q,x)==r)return true;
    	return false;
    }
    int main(){
    	cin>>p>>q>>r;
    	for(int i=2;i<=16;i++)
    		if(check(i)){
    			cout<<i;
    			return 0;
    		}
    	cout<<0;
    	return 0;
    }
    

    实际上,可以把 pqr 都转成 10 进制,看合不合法。

    #include <bits/stdc++.h>
    using namespace std;
    int work(int x,string st){
    	int ans=0;
        for(int i=0;i<st.size();i++)
        	if(st[i]-'0'>=x)return 0;//判断是否合法
            ans=ans*x+st[i]-'0';
        }return ans;
    }
    int main(){
    	string p,q,r;
    	cin>>p>>q>>r;
    	for(int i=2;i<=16;i++){
    		int p2=work(i,p),q2=work(i,q),r2=work(i,r);
    		if(p2*q2==r2){
    			cout<<i<<endl;
    			return 0;
    		}
    	}puts("0");
    	return 0;
    }
    

    T4

    大模拟,不讲。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    vector<int>v;
    int main(){
    	v.push_back(0);
    	int n,m,i;
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=n;i++){
    		int x;
    		cin>>x;
    		v.push_back(x);
    	}
    	for(i=1;i<=m;i++){
    		int x,y;
    		cin>>x>>y;
    		v.insert(v.begin()+y+1,x);
    		y++;
    		int l=y,r=y;
    		while(v[l-1]==v[y]&&l-1>0)l--;
    		while(v[r+1]==v[y]&&r+1<v.size())r++;
    		if(r-l>1){
    			for(int j=l;j<=r;j++)v.erase(v.begin()+l);
    			y=l-1;
    		}
    		while(v.size()>2){
    			int l=y,r=y;
    			while(v[l-1]==v[y]&&l-1>0)l--;
    			while(v[r+1]==v[y]&&r+1<v.size())r++;
    			if(r-l+1<3||r==y)break;
    			else{
    				v.erase(v.begin()+l,v.begin()+r+1);
    				y=l-1;
    			}
    		}
    	}cout<<v.size()-1;
    	return 0;
    }
    

    T5

    搜索

    这是最基本的搜索。有 4040 分。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k;
    int dfs(int n,int k){
    	if(k==1)return n;
    	int ans=INT_MAX;
    	for(int i=1;i<=n;i++){
    		if(n%i==0)ans=min(ans,min(i+dfs(n/i,k-1),n/i+dfs(i,k-1)));
    	}return ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(n,k);
    	return 0;
    }
    

    之后,有 22 种方法,先介绍第 11 种。

    11

    这个是标程的方法,最终效果会比我的方法慢,但是代码极为简短。

    首先,对于上面的代码,可以加上记忆化。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k;
    map<int,map<int,int> >mp;
    int dfs(int n,int k){
    	if(k==1)return n;
    	if(mp[n][k])return mp[n][k];
    	int ans=INT_MAX;
    	for(int i=1;i<=n;i++){
    		if(n%i==0)ans=min(ans,min(i+dfs(n/i,k-1),n/i+dfs(i,k-1)));
    	}return mp[n][k]=ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(n,k);
    	return 0;
    }
    

    依旧只有 4040 分。

    继续优化,我们发现枚举约数可以优化。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k;
    map<int,map<int,int> >mp;
    int dfs(int n,int k){
    	if(k==1)return n;
    	if(mp[n][k])return mp[n][k];
    	int ans=INT_MAX;
    	for(int i=1;i*i<=n;i++){
    		if(n%i==0)ans=min(ans,min(i+dfs(n/i,k-1),n/i+dfs(i,k-1)));
    	}return mp[n][k]=ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(n,k);
    	return 0;
    }
    

    这样就有 8080 分了。

    还可以在哪里优化呢?

    我们发现 kk 很大,而 nn 的质因子个数并不多。

    可以证明(显然)nn 的质因子小于 lognlog {n}

    那么 kk 这么大,显然就是有很多很多的 11

    可以让i22 开始。

    Q:如果是质数怎么办?返回INT_MAX显然是错的。

    A:所以我们需要把ans的初值赋成n+k-1

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k;
    map<int,map<int,int> >mp;
    int dfs(int n,int k){
    	if(k==1)return n;
    	if(mp[n][k])return mp[n][k];
    	int ans=n+k-1;
    	for(int i=2;i*i<=n;i++){
    		if(n%i==0)ans=min(ans,min(i+dfs(n/i,k-1),n/i+dfs(i,k-1)));
    	}return mp[n][k]=ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(n,k);
    	return 0;
    }
    

    这样就有100分了。

    最大的点跑了0.234s

    22

    我们先增加一个参数l,让后面的数字全部要geql

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k;
    ll dfs(int l,int n,int k){
    	if(k==1)return n;
    	ll ans=INT_MAX;//可能会炸出负数,所以要long long
    	for(int i=l;i<=n;i++){
    		if(n%i==0)ans=min(ans,i+dfs(i,n/i,k-1));
    	}return ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(1,n,k);
    	return 0;
    }
    

    依旧只有 4040 分。

    继续优化,我们发现可以加记忆化。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    map<int,map<int,map<int,int> > >mp;
    int n,k;
    ll dfs(int l,int n,int k){
    	if(k==1)return n;
    	if(mp[l][n][k])return mp[l][n][k];
    	ll ans=INT_MAX;
    	for(int i=l;i<=n;i++){//这里
    		if(n%i==0)ans=min(ans,i+dfs(i,n/i,k-1));
    	}return mp[l][n][k]=ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(1,n,k);
    	return 0;
    }
    

    依旧是 4040qwqqwq。。。

    继续优化,我们发现枚举约数可以优化。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k;
    ll dfs(int l,int n,int k){
    	if(k==1)return n;
    	ll ans=INT_MAX;
    	for(int i=l;i*i<=n;i++){
    		if(n%i==0)ans=min(ans,i+dfs(i,n/i,k-1));
    	}return ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(1,n,k);
    	return 0;
    }
    

    这样就有 8080 分了。

    还可以在哪里优化呢?

    我们发现 kk 很大,而 nn 的质因子个数并不多。

    可以证明(显然)nn 的质因子小于 lognlog {n}

    那么 kk 这么大,显然就是有很多很多的 11

    我们可以让l22 开始。

    Q:如果是质数怎么办?返回INT_MAX显然是错的。

    A:所以我们需要把ans的初值赋成n+k-1

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k;
    ll dfs(int l,int n,int k){
    	if(k==1)return n;
    	ll ans=n+k-1;
    	for(int i=l;i*i<=n;i++){
    		if(n%i==0)ans=min(ans,i+dfs(i,n/i,k-1));
    	}return ans;
    }
    int main(){
    	read(n);read(k);
    	cout<<dfs(2,n,k);
    	return 0;
    }
    

    这样就有100分了。

    最大的点跑了0.093s

    也算是一个很大的突破。

    Q:还有哪里可以优化吗?

    A:其实还是有的。

    我们看 dfsdfs 里的 ii。由于 ii 是保证单调不下降的,所以 ikni^{k}leq n

    这样的话,我们可以用到快速幂的方法。

    但是,你会发现,这个是假的,因为我们把 1 放到了最后处理,所以此优化和上面的优化不可兼用,我们把上面的优化拿掉。

    当然,因为 kk 过大,我们还得压缩一下 kk 的范围。

    七七八八的优化搞到最后,代码差不多是这样的

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    ll n,k,x=1,L=1,R=35,s;
    ll pw(ll x,ll y){
    	ll ans=1;
    	while(y){
    		if(y&1)ans=ans*x;
    		y>>=1;
    		x=x*x;
    	}return ans;
    }
    map<int,map<int,map<int,int> > >mp;
    ll dfs(ll l,ll n,ll k){
    	if(k==1)return n;
    	if(n==1)return k;
    	if(mp[l][n][k])return mp[l][n][k];
    	ll ans=INT_MAX;
    	ll Lft=l-1,Rgt=10000;
    	while(Lft+1<Rgt){
    		ll Mid=(Lft+Rgt)>>1;
    		if(pow(Mid,k)<=n)Lft=Mid;
    		else Rgt=Mid;
    	}
    	for(ll i=l;i<=Lft;i++){
    		if(n%i==0)ans=min(ans,i+dfs(i,n/i,k-1));
    	}return mp[l][n][k]=ans;
    }
    int main(){
    	read(n);read(k);
    	int x=n;
    	for(int i=2;i*i<=n;i++)
    		while(x%i==0)x/=i,s++;
    	if(x)s++;
    	if(k>s)cout<<dfs(1ll,n,s)+k-s;
    	else cout<<dfs(1ll,n,k);
    	return 0;
    }
    

    最大的点跑了0.106s

    当然最后的用时也差不多。

    实际上,我们问题想回来,如果 kk 过于大,方法肯定是唯一的。

    因为 x,y2x,y geq 2 的情况下 x×yx+yx imes y geq x+y。所以,最优解显然是 nn 的质因子和 ++ (k(k - nn 的质因子个数 ))

    我们可以这样写一下。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    int n,k,s;
    int pw(int x,int y){
    	int ans=1;
    	while(y){
    		if(y&1)ans=ans*x;
    		y>>=1;
    		x=x*x;
    	}return ans;
    }
    map<int,map<int,map<int,int> > >mp;
    int dfs(int l,int n,int k){
    	if(k==1)return n;
    	if(mp[l][n][k])return mp[l][n][k];
    	int ans=n+k-1,Lft=l-1,Rgt=100;
    	while(Lft+1<Rgt){//这边的话,明显是有二分性的,所以直接二分。
    		ll Mid=(Lft+Rgt)>>1;
    		if(pow(Mid,k)<=n)Lft=Mid;
    		else Rgt=Mid;
    	}
    	for(int i=l;i<=Lft;i++){//就不要一个一个去pow了
    		if(n%i==0)ans=min(ans,i+dfs(i,n/i,k-1));
    	}return mp[l][n][k]=ans;
    }
    int main(){
    	vector<int>v;
    	read(n);read(k);
    	int x=n;
    	for(int i=2;i*i<=n;i++)
    		while(x%i==0)x/=i,s+=i,v.push_back(i);
    	if(x)s+=x,v.push_back(x);
    	if(k>=v.size())cout<<s+k-v.size();//就是上面的式子
    	else cout<<dfs(2ll,n,k);//2个优化一起来
    	return 0;
    }
    

    最慢的点跑了0.015s

    我觉得这应该就是最优解了吧。

    T6

    我们去枚举 kk,然后贪心去check

    复杂度 O(n3)O(n^3)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>inline void write(T x){
    	if(x<0)putchar('-'),x*=-1;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    template<typename T>inline void writen(T x){
    	write(x);
    	puts("");
    }
    int n,a[3010],ans=INT_MAX,xi,b[3010];
    queue<int>q;
    int work(int x){
    	for(int i=1;i<=n;i++)b[i]=a[i];
    	int s=0;
    	for(int i=1;i<=n;i++){
    		if(b[i]%2==1){
    			if(i+x-1>n)return INT_MAX;
                for(int i=1;i<k;i++)b[i+k]^=1;
    			s++;
    		}
    	}return s;
    }
    int main(){
    	read(n);
    	for(int i=1;i<=n;i++)read(a[i]);
    	for(int i=1;i<=n;i++){
    		int x=work(i);
    		if(x<ans){
    			xi=i;
    			ans=x;
    		}
    	}cout<<xi;
    	return 0;
    }
    

    这样就有90分了。

    100分做法有2种。都是去优化上述算法给后面数加的浪费时间的问题。

    • 可以差分
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>inline void write(T x){
    	if(x<0)putchar('-'),x*=-1;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    template<typename T>inline void writen(T x){
    	write(x);
    	puts("");
    }
    int n,a[3010],ans=INT_MAX,xi,b[3010];
    queue<int>q;
    int work(int x){
    	memset(b,0,sizeof(b));
    	int s=0;
    	for(int i=1;i<=n;i++){
    		b[i]+=b[i-1];
    		if((b[i]+a[i])%2==1){
    			if(i+x-1>n)return INT_MAX;
    			b[i]++;
                b[i+x]--;
    			s++;
    		}
    	}return s;
    }
    int main(){
    	read(n);
    	for(int i=1;i<=n;i++)read(a[i]);
    	for(int i=1;i<=n;i++){
    		int x=work(i);
    		if(x<ans){
    			xi=i;
    			ans=x;
    		}
    	}cout<<xi;
    	return 0;
    }
    
    • 可以用单调队列
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>inline void write(T x){
    	if(x<0)putchar('-'),x*=-1;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    template<typename T>inline void writen(T x){
    	write(x);
    	puts("");
    }
    int n,a[3010],ans=INT_MAX,xi,b[3010];
    queue<int>q;
    int work(int x){
    	while(q.size())q.pop();
    	int s=0;
    	for(int i=1;i<=n;i++){
    		while(q.size()&&i-q.front()>=x)q.pop();
    		if((a[i]+q.size())%2==1){
    			if(i+x-1>n)return INT_MAX;
    			s++,q.push(i);
    		}
    	}return s;
    }
    int main(){
    	read(n);
    	for(int i=1;i<=n;i++)read(a[i]);
    	for(int i=1;i<=n;i++){
    		int x=work(i);
    		if(x<ans){
    			xi=i;
    			ans=x;
    		}
    	}cout<<xi;
    	return 0;
    }
    

    T7

    这道题,我们可以想一下,矩形的面积跟 22 条边有关。

    对于每个点,我们算出 33 个数,lftrgtup

    lft:即此点最多能向左延伸到哪一列。(初值为j)

    for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++)
    		if(a[i][j]&&a[i][j-1])lft[i][j]=lft[i][j-1];
    

    rgt:即此点最多能向右延伸多少哪一列。(初值为j)

    for(int i=1;i<=n;i++)
    		for(int j=m;j>=1;j--)
    			if(a[i][j]&&a[i][j+1])rgt[i][j]=rgt[i][j+1];
    

    up:即此点最多能向上延伸多少个格子数。(初值为1)

    dpdp 边求。

    现在我们就说说 dpdp 吧。

    for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++){
    		if(a[i][j]&&a[i-1][j]){
    			lft[i][j]=max(lft[i-1][j],lft[i][j]);//在up最优的情况下,左端点的距离要更新
    			rgt[i][j]=min(rgt[i-1][j],rgt[i][j]);//在up最优的情况下,右端点的距离要更新
    			up[i][j]=up[i-1][j]+1;
    		}
    		int x=rgt[i][j]-lft[i][j]+1;
    		ans=max(ans,x*up[i][j]);
    	}
    

    其实就是找高度最高的矩形,为什么这样是正确的呢。

    我们可以这样想一下。我们的算法本质就是,i,ji,j 最多往上的长度做矩阵一条边,这个就是 upi,jup_{i,j} 干的事情,然后 lfti,jlft_{i,j}rgti,jrgt_{i,j} 则是要在 upi,jup_{i,j} 最优的情况下,让另一条边也最优。

    你可以再想一下,下面这张图,最大子矩阵是橙色方框圈起来的。我们可以发现,最大子矩阵的四条边,每条边要么是靠到边界,要么是靠到障碍物。也就是说,最大子矩阵的上边界一定会靠到障碍物或边界。我们的算法就相当于确定了下边界,然后用 upup 数组又确定了上边界。然后用 lftlftrgtrgt 确定左边界和右边界。213.png

    如果还是不懂的话,可以再想一下,我来模拟一下。

    这就是我们 upup 做的事。

    213.png

    然后呢,对于每条线,我们要让他们的上边界尽可能的长。

    213.png

    再回来看看代码:

    #include <bits/stdc++.h>
    using namespace std;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>void write(T x){
    	if(x<0)putchar('-'),x*=-1;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    int a[2010][2010],lft[2010][2010],rgt[2010][2010],up[2010][2010],ans;
    int main(){
    	int n,m;
    	read(n);read(m);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			read(a[i][j]);
    			a[i][j]^=1;
    			lft[i][j]=j;
    			rgt[i][j]=j;
    			up[i][j]=1;
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(a[i][j]&&a[i][j-1])lft[i][j]=lft[i][j-1];
    	for(int i=1;i<=n;i++)
    		for(int j=m;j>=1;j--)
    			if(a[i][j]&&a[i][j+1])rgt[i][j]=rgt[i][j+1];
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			if(a[i][j]&&a[i-1][j]){
    				lft[i][j]=max(lft[i-1][j],lft[i][j]);
    				rgt[i][j]=min(rgt[i-1][j],rgt[i][j]);
    				up[i][j]=up[i-1][j]+1;
    			}
    			int x=rgt[i][j]-lft[i][j]+1;
    			ans=max(ans,x*up[i][j]);
    		}
    	write(ans);
    	return 0;
    }
    

    是不是就懂了qwqqwq。。。

    我才不告诉你,这个其实就是单调队列

  • 相关阅读:
    Java——GUI
    linux变量
    shell脚本
    linux查找文件命令
    composer的安装
    restful的nginx配置方法
    api调用安全
    PHP设置Cookie的HTTPONLY属性
    php的异常处理
    php错误报告
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/12816962.html
Copyright © 2011-2022 走看看