2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest-gym 102091 题解

A. Flying Squirrel

题意:给你n根柱子,高度分别为a[i]。m次询问:给两个数X,Y。从X出发到Y为止,当Y=0表示可以从X出发,任意位置停止。每一次行走的条件是中间不能有高于或者等于当前柱子高度。

问我们最多能走多少次?

首先我们有一个观察,在当前柱子上。我们选择下一根柱子去走的时候,肯定会考虑向左或者向右能走的所有最高的柱子,这相当于从这个点向他们连边。那不妨我们直接考虑从最高的柱子开始走,每次

向能走到的所有最高的柱子连边,并且递归的去建树,建树的时候顺便把无目的地的答案给处理出来。显然,如果有解的话,我们就把他们之间的深度差输出。

 

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

int st[MAXN][20], lg[MAXN];

int h[MAXN], ans[MAXN], dep[MAXN];

int n, m;

int query(int L, int R){
    int k=lg[R-L+1];
    if(h[st[L][k]]>=h[st[R-(1<<k)+1][k]])return st[L][k];
    else return st[R-(1<<k)+1][k];
}

int dfs(int L, int R, int d){
    if(L>R)return -1;

    int all=0;
    int p=query(L, R);
    dep[p]=d;
    ans[p]=dfs(L,p-1,d+1)+1;
    all=max(all,ans[p]);

    while(p<R){
        int q=query(p+1,R);
        if(h[p]!=h[q])break;

        int t=dfs(p+1,q-1,d+1)+1;
        ans[p]=max(ans[p],t);
        all=max(all,ans[p]);
        dep[q]=d;
        ans[q]=t;
        p=q;
    }

    ans[p]=max(ans[p],dfs(p+1,R,d+1)+1);
    all=max(all,ans[p]);

    return all;
}

int main(){
    n=read();m=read();

    for(int i=1;i<=n;++i)h[i]=read(), st[i][0]=i;
    for(int i=2;i<=n;++i)lg[i]=lg[i/2]+1;

    for(int j=1;j<=20;++j){
        for(int i=1;i+(1<<j)-1<=n;++i){
            if(h[st[i][j-1]]>=h[st[i+(1<<j-1)][j-1]])st[i][j]=st[i][j-1];
            else st[i][j]=st[i+(1<<j-1)][j-1];
        }
    }

    dfs(1,n,0);

    while(m--){
        int l, r;
        l=read();
        r=read();

        if(!r){
            cout<<ans[l]<<endl;
        }else{
            if(h[l]==h[r]){
                cout<<"0"<<endl;
            }else{
                if(h[l]>h[r])swap(l,r);/*ºÃ¶àbug*/
                int t;
                if(l<r)t=query(l,r-1);
                else t=query(r+1,l);

                if(h[t]>=h[r]){
                    cout<<"0"<<endl;
                }else{
                    cout<<dep[l]-dep[r]<<endl;
                }
            }
        }
    }

    return 0;
}

/*
12 8
2 3 4 4 4 3 3 3 1 2 5 2
3 0
4 0
5 0
7 0
7 11
7 9
11 1
9 12
*/
View Code

 

B. 留坑,大佬说分类讨论,打表出特殊情况。

C. Evolution Game

  现在有一些怪物,每一种分别有x个眼睛和y个角。眼睛数量有一个上界N,且每一个眼睛数量都是有其对应的角数量的,你可以以任意一类出生。再给定一个值w,表示眼睛数量的变化范围。i.e. 进化一次,眼睛数量的范围是[x-w,x+w]。还有一个限制条件是每次角的数量只能增加。问最多能进化多少次?

  温暖的签到,记忆化搜索即可。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 5'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

int h[MAXN];

int f[MAXN];

int n, w;

int dfs(int x){
    if(f[x]!=-1)return f[x];

    f[x]=0;

    for(int i=max(1,x-w);i<=min(n,x+w);++i){
        if(h[i]>h[x]){
            f[x]=max(f[x],1+dfs(i));
        }
    }

    return f[x];
}

int main(){
    n=read();w=read();

    for(int i=1;i<=n;++i){
        h[i]=read();
        f[i]=-1;
    }

    int ans=0;
    for(int i=1;i<=n;++i){
        ans=max(ans,dfs(i));
    }

    cout<<ans;
    return 0;
}

/*
5 5
5 3 2 1 4
*/
View Code

D. Bus Stop

  有一条直线,上面n个点,现在要安排一些点,使得原来的点的左右10单位内至少有一个新安排的点,问最少的新安排上的点的数量?

  从左向右贪心即可。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define MP make_pair
#define mid (l+r>>1)
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 2'000'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

int d[MAXN];

void solve(){
    int n=read();
    for(int i=1;i<=n;++i)d[i]=read();

    if(n==0){
        cout<<"0"<<endl;
        return;
    }
    int cnt=1;
    int r=d[1]+10;
    int idx=1;

    while(1){
        while(abs(d[idx]-r)<=10)++idx;
        if(idx>n)break;
        else{
            r=d[idx]+10;
            ++cnt;
        }
    }

    printf("%d
",cnt);
}

int main(){
    int cases;cases=read();
    while(cases--){
        solve();
    }

    return 0;
}
/*
2
5
1 2 3 200 210
4
10 30 80 200
*/
View Code

E. How many groups

  给你一个n个数的数组,你可以进行两次操作,包括将数组里的一个数+1或者-1,但不能对同一个元素操作两次。将两个数分成一组的条件是他们之间的差值的绝对值小于2。问其中的最大一组的size是多少?

  设dp[x][i]为以x结尾,且总操作次数为i的组的最大尺寸,然后根据决策去转移就好了。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 205;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

int f[MAXN][3];
int temp[MAXN][3];
int a[MAXN];
int n;

int main(){
    int t;t=read();
    int kase=1;
    while(t--){
        n=read();memset(f,0,sizeof f);
        for(int i=1;i<=n;++i)a[i]=read();
        sort(a+1,a+n+1);

        int ans=1;

        for(int i=1;i<=n;++i){
            int x=a[i];
            for(int j=max(x-3,0);j<=x+3;++j){
                for(int k=0;k<=2;++k){
                    temp[j][k]=f[j][k];
                }
            }
            for(int j=2;j>=0;--j)f[x][j]=max({temp[x+2][j],temp[x+1][j],temp[x][j],temp[x-1][j],x>=2?temp[x-2][j]:0})+1;
            for(int j=2;j>=1;--j)f[x-1][j]=max({temp[x+1][j-1],temp[x][j-1],temp[x-1][j-1],x-2>=0?temp[x-2][j-1]:0,x-3>=0?temp[x-3][j-1]:0})+1;
            for(int j=2;j>=1;--j)f[x+1][j]=max({temp[x+3][j-1],temp[x+2][j-1],temp[x+1][j-1],temp[x][j-1],temp[x-1][j-1]})+1;
        }

        for(int i=1;i<=200;++i)
            for(int j=0;j<=2;++j)ans=max(ans,f[i][j]);
        cout<<"Case "<<kase++<<": "<<ans<<endl;
    }

    return 0;
}

/*
5
10
2 1 7 4 3 8 9 12 13 20
3
1 2 3
4
1 2 7 8
3
10 30 20
2
5 5

Case 1: 9
Case 2: 3
Case 3: 2
Case 4: 1
Case 5: 2

*/
View Code

F. Lucky Pascal Triangle

  给你一个杨辉三角,问前n行中能被7整除的数的个数是多少。

  首先应该打表找规律,这里只说规律。首先可以发现能被7整除的数是呈块状分布的。第一块从[1,7^1-1],第二块[7^1,7^2-1],第三块[7^2,7^3-1]...。其次,每一块里面都有21块大的块且每一行的个数为等差数列,

  28块为前面所有的行组成的块。我们就能直接预处理出第一块,第二块...,再数出大块里面的块的个数,其他的递归求解。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline LL read(){
    LL res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T& a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T& a, T b){if(b>a)a=b;}

//打表找规律,每一个以7^i为结尾的数量都是有规律的
//f[i]=f[i-1]*28+(7^(i-1)-1)*7^(i-1)/2*28(具体来讲是考虑28个上一个块。在考虑21个新形成的块)


map<LL, LL> H;

LL powmod(LL x, LL y){
    LL res=1;
    while(y){
        if(y&1)
            res=res*x%MOD;
        y>>=1;
        x=x*x%MOD;
    }
    return res;
}

LL inv2;

void init(){
    LL base=7;
    H[base-1]=0;
    base=49;
    while(base<=(LL)(1e18)){
        LL t=base/7;
        H[base-1]=(28*H[t-1]%MOD+21*inv2%MOD*((t-1)%MOD)%MOD*(t%MOD)%MOD)%MOD;
        base*=7;
    }
}

LL calc(LL n){
    if(n<=6)return 0;
    LL ans=0;
    LL base=0;
    for(auto it:H){
        LL x=it.fi,y=it.sd;
        if(x<=n){
            ans=y;//先 take care 整块的情况
            base=x;
        }else break;
    }

    ++base;

    LL a=base;//考虑接下来不为整块的情况
    LL time=1;

    LL now=base%MOD*((base-1)%MOD)%MOD*inv2%MOD;

    while(a+base<=n){
        ans+=now*time%MOD;//一个大块里面的小块
        ans%=MOD;

        ++time;
        ans+=H[base-1]*time%MOD;
        ans%=MOD;
        a+=base;
    }

    if(n-a+1==base){
        ans=(ans+(base%MOD)*((base-1)%MOD)%MOD*inv2%MOD*time%MOD)%MOD;//是整块
    }else{
        ans=(ans+((2*base-n+a-2)%MOD+MOD)%MOD*((n-a+1)%MOD)%MOD*inv2*time%MOD)%MOD;//等差数列而已
    }
    ans=(ans+(time+1)*calc(n-a)%MOD)%MOD;
    return ans;
}

int main(){
    inv2=powmod(2,MOD-2);
    LL cases;cases=read();
    LL kase=1;
    init();
    while(cases--){
        LL n;n=read();
        cout<<"Case "<<kase++<<": "<<calc(n)<<endl;
    }

    return 0;
}


/*
5
1
5
10
15
100000
*/
View Code

G. Communication

  给n个点的图,求其DAG的节点个数。

  tarjan缩点。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define MP make_pair
#define mid (l+r>>1)
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 205;
const int MAXM = 10'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

#define go(e,u) for(int e=head[u];e;e=Next[e])
int to[MAXM<<1],Next[MAXM<<1],head[MAXN],tol;

void add_edge(int u,int v){
    Next[++tol]=head[u];to[tol]=v;head[u]=tol;
//    Next[++tol]=head[v];to[tol]=u;head[v]=tol;
}

int n, m;

int dfn[MAXN],low[MAXN],dfncnt;

int st[MAXN],top;

int scc[MAXN], sc;

void init(){
    tol=0;top=0;sc=0;
    dfncnt=0;
    memset(dfn,0,sizeof dfn);
    memset(low,0,sizeof low);
    memset(head,0,sizeof head);
    memset(Next,0,sizeof Next);
    memset(to,0,sizeof to);
    memset(scc,0,sizeof scc);
}

void tarjan(int u){
    dfn[u]=low[u]=++dfncnt;
    st[++top]=u;

    go(e,u){
        int v=to[e];

        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(!scc[v]){
            low[u]=min(low[u],low[v]);
        }
    }

    if(low[u]==dfn[u]){
        ++sc;
        while(st[top]!=u){
            scc[st[top]]=sc;
            --top;
        }
        scc[st[top]]=sc;
        --top;
    }
}

void solve(){
    init();
    n=read();m=read();
    for(int i=1;i<=m;++i){
        int u, v;
        u=read(),v=read();
        ++u,++v;
        add_edge(u,v);
    }

    for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);

    cout<<sc<<endl;
}

int main(){
    int cases;cases=read();
    while(cases--){
        solve();
    }

    return 0;
}
/*
3
6
2 0 5 5 0
5
7 0 1 0 2 1 0 1 3 2 4 3 1 4 2
3
4 0 1 0 2 1 0 1 2
*/
View Code

H. As rich as Crassus

  给你三个数的立方值关于三个模数的模值,且每一个模值都互质,求这三个数。

  CRT,但是会爆long long,所以需要龟速乘。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline LL read(){
    LL res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

LL P,mods[4],rem[4];

LL mul(LL x, LL y){
    LL ans=0;
    while(y){
        if(y&1)ans=(ans+x)%P;
        y>>=1;
        x=(x+x)%P;
    }
    return (ans%P+P)%P;
}

LL exgcd(LL a, LL b, LL& x, LL& y){
    if(!b){x=1;y=0;return a;}
    else{
        LL d=exgcd(b,a%b,y,x);
        y-=(a/b)*x;
        return d;
    }
}

LL CRT(){
    for(int i=1;i<=3;++i)P*=mods[i];

    LL ans=0;
    for(int i=1;i<=3;++i){
        LL x,y;
        LL d=exgcd(P/mods[i],mods[i],x,y);
        x=(x%mods[i]+mods[i])%mods[i];
        if(d!=1)return -1;
        else{
            ans=(ans+mul(mul(P/mods[i],x)%P,rem[i])%P)%P;
        }
    }
    return (ans%P+P)%P;
}

void solve(){
    P=1;
    for(int i=1;i<=3;++i)mods[i]=read();
    for(int i=1;i<=3;++i)rem[i]=read();

    LL ans=CRT();
    if(ans==-1){
        cout<<"-1"<<endl;
    }else{
        LL t=(LL)pow(ans,1.0/3.0);
        if(t*t*t<ans)cout<<t+1<<endl;
        else cout<<t<<endl;
    }
}

int main(){
    LL cases;cases=read();
    while(cases--){
        solve();
    }
    return 0;
}

/*
2
6 11 19
5 4 11
25 36 7
16 0 6
*/
View Code

I. Bowabowaukulipukuli

  防AK题,溜了溜了。

J. Floating-Point Hazard

  给你一个函数f[x]=(x+1e-15)^(1/3)-(x)^(1/3),给一个下界lo, 一个上界hi,求这个区间内函数值的和。

  这个算式有一些特殊形式,如果分母除一个1e-15,就是求导式。考虑到1e-15已经足够小,这个算式可以用f'[x]*1e-15来代替。求和即可。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

int lo, hi;

void solve(){
    double ans=0.0;
    for(int i=lo;i<=hi;++i){
        ans+=(1.0/3)*pow(i,-2.0/3.0);
    }
    int cnt=15;
    while(ans<1.0){
        ans*=10.0;
        ++cnt;
    }
    while(ans>10){
        ans/=10;
        --cnt;
    }

    printf("%.5fE%.3d
",ans,-cnt);

}

int main(){
    while((cin>>lo>>hi)&&(lo+hi)){
        solve();
    }

    return 0;
}
View Code

K. The Stream of Corning 2

  给你m次询问或修改,op=1时,给一个值和它的出现时间,消失时间。op=2问当前的rank[k]。

  将询问离线,写一颗权值线段树即可通过(值在1e6内甚至都不用离散化。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define MP make_pair
#define mid (l+r>>1)
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;


namespace FastIO {
    const int SIZE = 1 << 16;
    char buf[SIZE], str[64];
    int l = SIZE, r = SIZE;
    int read(char *s) {
        while (r) {
            for (; l < r && buf[l] <= ' '; l++);
            if (l < r) break;
            l = 0, r = int(fread(buf, 1, SIZE, stdin));
        }
        int cur = 0;
        while (r) {
            for (; l < r && buf[l] > ' '; l++) s[cur++] = buf[l];
            if (l < r) break;
            l = 0, r = int(fread(buf, 1, SIZE, stdin));
        }
        s[cur] = '';
        return cur;
    }
    template<typename type>
    bool read(type &x, int len = 0, int cur = 0, bool flag = false) {
        if (!(len = read(str))) return false;
        if (str[cur] == '-') flag = true, cur++;
        for (x = 0; cur < len; cur++) x = x * 10 + str[cur] - '0';
        if (flag) x = -x;
        return true;
    }
    template <typename type>
    type read(int len = 0, int cur = 0, bool flag = false, type x = 0) {
        if (!(len = read(str))) return false;
        if (str[cur] == '-') flag = true, cur++;
        for (x = 0; cur < len; cur++) x = x * 10 + str[cur] - '0';
        return flag ? -x : x;
    }
} using FastIO::read;

const int MAXN = 200005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

int st[MAXN],top;

int ans[MAXN];

int T[MAXN<<4];//权值线段树维护排名为第几的值分别有多少个

void update(int nd, int l, int r, int pos, int val){
    if(l==r){
        T[nd]+=val;
        return;
    }

    if(pos<=mid)update(lson,l,mid,pos,val);
    else update(rson,mid+1,r,pos,val);

    T[nd]=T[lson]+T[rson];
}

int query(int nd, int l, int r, int k){
    if(l==r){
        return l;
    }
    if(T[lson]>=k)return query(lson,l,mid,k);
    else return query(rson,mid+1,r,k-T[lson]);
}

struct qq{
    int op,t,val,id;
}Q[MAXN];


bool cmp2(const qq& a, const qq& b){
    if(a.t==b.t)return a.op<b.op;
    return a.t<b.t;
}

int cnt,cases,kase;

void solve(){
    cnt=top=0;
    int n;read(n);

    for(int i=1;i<=n;++i){
        int opop;
        int x,y,z;
        read(opop);
        if(opop==1){
            read(x),read(y),read(z);
            Q[++cnt].op=1;
            Q[cnt].t=x;
            Q[cnt].val=y;
            Q[cnt].id=i;
            Q[++cnt].op=3;
            Q[cnt].t=z;
            Q[cnt].val=y;
            Q[cnt].id=i;
            st[++top]=x;
            st[++top]=z;
        }else{
            read(x),read(y);
            Q[++cnt].op=2;
            Q[cnt].t=x;
            Q[cnt].val=y;
            Q[cnt].id=i;
            st[++top]=x;
        }
    }

    sort(st+1,st+top+1);
    top=unique(st+1,st+1+top)-st-1;
    for(int i=1;i<=cnt;++i)Q[i].t=lower_bound(st+1,st+1+top,Q[i].t)-st;
    sort(Q+1,Q+cnt+1,cmp2);

    for(int i=1;i<=cnt;++i){
        qq it=Q[i];
        if(it.op==1){
            update(1,1,1e6,it.val,1);
        }else if(it.op==2){
            if(it.val>T[1]){
                ans[it.id]=-1;
                continue;
            }
            int rk=query(1,1,1e6,it.val);
            ans[it.id]=rk;
        }else{
            update(1,1,1e6,it.val,-1);
        }
    }

    printf("Case %d:
",kase);//这里一直T
    for(int i=1;i<=n;++i)if(ans[i]!=0){
        printf("%d
",ans[i]);
        ans[i]=0;
    }
}

int main(){
    read(cases);
    for(kase=1;kase<=cases;++kase){
        solve();
    }
    return 0;
}

/*
1
10
1 1 10 7
1 2 9 4
2 4 1
1 5 2 6
2 6 2
2 7 2
1 8 2 20
1 9 1 15
1 10 3 13
2 11 3
*/
View Code

L. Largest Allowed Area

  给你一个大小为R*C的表格,元素只有0或者1。求最多包含一个1的最大正方形边长。

  前缀和加二分。队友被T的飞起,还好我没做这个题嘿嘿。

#include<bits/stdc++.h>

#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define MP make_pair
#define mid (l+r>>1)
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 1'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

int preSum[MAXN][MAXN];

int R, C;

int get(int x1, int y1, int x2, int y2){
    return preSum[x2][y2]-preSum[x1-1][y2]-preSum[x2][y1-1]+preSum[x1-1][y1-1];
}

bool check(int len){
    for(int i=1;i<=R-len+1;++i){
        for(int j=1;j<=C-len+1;++j){
            if(get(i,j,i+len-1,j+len-1)<=1)return true;
        }
    }

    return false;
}

void solve(){
    R=read();C=read();
    for(int i=1;i<=R;++i){
        for(int j=1;j<=C;++j){
            preSum[i][j]=read();
        }
    }

    for(int i=1;i<=R;++i){
        for(int j=1;j<=C;++j){
            preSum[i][j]+=preSum[i-1][j]+preSum[i][j-1]-preSum[i-1][j-1];
        }
    }

    int l=1,r=min(R,C);
    int ans=0;
    while(l<=r){
        if(check(mid)){
            ans=mid;
            l=mid+1;
        }else{
            r=mid-1;
        }
    }
    cout<<ans<<endl;
}

int main(){
    int cases;cases=read();
    while(cases--){
        solve();
    }

    return 0;
}

/*
10 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
*/
View Code

 

原文地址:https://www.cnblogs.com/JohnRan/p/12573699.html