9.22

100+30+70=200
T1水题,单调队列

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define N 2005
using namespace std;
int n,m,ans,a[N],f[N][N],l[N],r[N],q[N];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)scanf("%d",&a[j]);
        for(int j=m;j>=1;j--)f[i][j]=a[j]?f[i][j+1]+1:0;
    }
    for(int i=1,j,top;i<=m;i++){
        for(j=1,top=0;j<=n;j++){
            while(top>0&&f[q[top]][i]>=f[j][i])top--;
            l[j]=q[top]; q[++top]=j;
        }
        for(j=n,top=0,q[0]=n+1;j>=1;j--){
            while(top>0&&f[q[top]][i]>=f[j][i])top--;
            r[j]=q[top]; q[++top]=j;
        }
        for(j=1;j<=n;j++)
            ans=max(ans,min(r[j]-l[j]-1,f[j][i]));
    }
    printf("%d\n",ans);
    return 0;
}

T2标程,数据都是错的,其实A了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
struct data{
    LL x,y;
    bool operator < (const data &a)const{
        if(x==a.x)return y<a.y;
        return x<a.x;
    }
}d[10005];
int n,f[10005],ans;
LL c[10005];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&d[i].x,&d[i].y);
    sort(d+1,d+n+1);
    for(int i=1;i<=n;i++)c[i]=d[i].y;
    for(int i=n;i>=1;i--){
        f[i]=1;
        for(int j=n;j>i;j--)if(c[j]<c[i])
            f[i]=max(f[i],f[j]+1);
        ans=max(ans,f[i]);
    }
    printf("%d\n",ans);
    return 0;
}

T3,莫队+O3+快读卡过。。
正解只按左端点排序,又是根号算法。。。

#pragma GCC optimize ("O3")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define N 1000050
using namespace std;
int be[N],n,m,nn,a[N],f[N];
struct QQ{
    int l,r,id;
}qu[N];
bool cmp1(QQ a,QQ b){
    if(be[a.l]!=be[b.l])return be[a.l]<be[b.l];
    if(a.r!=b.r)return a.r<b.r;
    return a.l<b.l; 
}
int num[N];
void work(){
    int l=1,r=0,sum=0;
    for(int i=1;i<=m;++i){
        while(r<qu[i].r){
            ++r;++num[a[r]];
            if(num[a[r]]==a[r])++sum;
            if(num[a[r]]==a[r]+1)--sum;
        }
        while(r>qu[i].r){
            --num[a[r]];
            if(num[a[r]]==a[r])++sum;
            if(num[a[r]]==a[r]-1)--sum;
            --r;
        }
        while(l<qu[i].l){
            --num[a[l]];
            if(num[a[l]]==a[l])++sum;
            if(num[a[l]]==a[l]-1)--sum;
            ++l;
        }
        while(l>qu[i].l){
            --l;++num[a[l]];
            if(num[a[l]]==a[l])++sum;
            if(num[a[l]]==a[l]+1)--sum;
        }
        f[qu[i].id]=sum;
    }
}
int read(){
    int a=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){a=a*10+(ch^48);ch=getchar();}
    return a;
}
int main(){
    //freopen("test.in","r",stdin);
    //freopen("my.out","w",stdout);
    n=read(); m=read();
    //nn=(int)sqrt(n);
    nn=2000;
    for(int i=1;i<=n;i++){
        a[i]=read();
        be[i]=(i-1)/nn+1;
    }
    for(int i=1;i<=m;i++){
        qu[i].l=read();qu[i].r=read();
        qu[i].id=i;
    }
    sort(qu+1,qu+m+1,cmp1);
    work();
    for(int i=1;i<=m;i++)
        printf("%d\n",f[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值