• Educational Round 66 题解


    作为橙名来水了一发……

    这次题目就比上次良心多了。7题有5题会做。

    然而风格仍然很怪异……还是练少了?


    A

    水题。不过一开始没注意细节挂了几发,罚时罚的真痛……

    明显是能除以 $k$ 就除以 $k$,否则就 $-1$。但注意不能直接最裸的模拟。

    时间复杂度 $O(Tlog n)$。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=100010;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
        char ch=getchar();ll x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int t;
    ll n,k,cnt;
    int main(){
        t=read();
        while(t--){
            n=read();k=read();
            cnt=0;
            while(n){
                if(n%k==0) n/=k,cnt++;
                else{
                    ll t=n/k*k;
                    cnt+=n-t;
                    n=t;
                }
            }
            cout<<cnt<<endl;
        }
    }
    View Code

    B

    堪比NOIP2017D1T2的模拟程序。

    有很多细节,然后我的同学们就全挂了,就我一个幸存???

    用 $y[i]$ 表示到第 $i$ 行时共会循环多少次,$hhh[i]$ 表示 $y[i]$ 是否溢出。

    代码写着也不是很难受。时间复杂度 $O(n)$。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=100010;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
        char ch=getchar();ll x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int l,stk[maxn],tp;
    char op[maxn][10];
    bool hhh[maxn];
    ll x,y[maxn],a[maxn];
    int main(){
        l=read();
        FOR(i,1,l){
            scanf("%s",op[i]+1);
            if(op[i][1]=='f') a[i]=read();
        }
        y[0]=1;
        FOR(i,1,l){
            if(op[i][1]=='f'){
                stk[++tp]=i;
                y[i]=y[i-1]*a[i];
                if(hhh[i-1] || y[i]>=(1ll<<32)) hhh[i]=true;
            }
            else{
                if(op[i][1]=='e') y[i]=y[stk[tp]-1],hhh[i]=hhh[stk[tp]-1],tp--;
                else{
                    y[i]=y[i-1];hhh[i]=hhh[i-1];
                    if(hhh[i]) return puts("OVERFLOW!!!"),0;
                    x+=y[i];
                    if(x>=(1ll<<32)) return puts("OVERFLOW!!!"),0;
                }
            }
        }
        cout<<x<<endl;
    }
    View Code

    C

    有一点点点点的难度。

    发现对于一个点,与它前 $k$ 近的点是一个长度为 $k$ 的区间。

    枚举这个区间,对于一个区间最优答案在中点取得。对所有中点取个最优即可。

    时间复杂度 $O(sum n)$。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=200020;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
        char ch=getchar();ll x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int t,n,k,a[maxn],x,y;
    int main(){
        t=read();
        while(t--){
            n=read();k=read()+1;
            FOR(i,1,n) a[i]=read();
            y=1e9;
            FOR(l,1,n-k+1){
                int r=l+k-1,mid=(a[l]+a[r])>>1;
                if(a[r]-a[l]<y) y=a[r]-a[l],x=mid;
            }
            printf("%d
    ",x);
        }
    }
    View Code

    D

    比B和C还水的水题。

    我们假设分割点是 $x_1,x_2,x_3,cdots,x_{k-1},x_k$。注意 $x_1=1$。那么题目中的式子就是 $sum suf[x_i]$。($suf$ 是后缀和)

    那么在 $suf[2],suf[3],cdots,suf[n]$ 中取前 $k-1$ 大,再与 $suf[1]$ 相加就是答案。

    时间复杂度 $O(nlog n)$。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=300030;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
        char ch=getchar();ll x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,k,a[maxn];
    ll suf[maxn],ans;
    int main(){
        n=read();k=read();
        FOR(i,1,n) a[i]=read();
        ROF(i,n,1) suf[i]=suf[i+1]+a[i];
        sort(suf+2,suf+n+1,greater<ll>());
        ans=suf[1];
        FOR(i,2,k) ans+=suf[i];
        cout<<ans;
    }
    View Code

    E

    开始有难度了。

    首先发现对于左端点相同的区间,只需要保留右端点最右的一个。

    (以下设询问区间为 $[x,y]$)

    然后假设 $[x,y_0]$ 已经被完全覆盖了,那么下一个要选的区间的左端点要 $le y_0$,且右端点尽可能右。

    设 $mx[l]$ 表示左端点 $le l$ 的区间中的最右右端点。

    那么问题就变成从 $x$ 开始跳,跳到 $mx[x]$,再跳到 $mx[mx[x]]$……一直跳跳到 $ge y$ 为止,问要多少步。

    那么就是显然的倍增了。

    设 $to[i][j]$ 表示从 $i$ 开始跳 $2^j$ 会跳到哪。那么有 $to[i][0]=mx[i],to[i][j]=to[to[i][j-1]][j-1]$。

    对于每个询问,先判无解。

    否则从 $19$ 到 $0$ 枚举 $j$。如果 $to[x][j]<y$ 那么把 $x$ 跳到 $to[x][j]$。

    这时当 $to[x][0]<y$ 那么无解,因为已经跳了 $2^20$ 步了,如果还没跳到那么说明没法再跳到了(只能在原地跳环)。否则因为有解,所以枚举完后再跳一步一定能 $ge y$。

    时间复杂度 $O(n+(q+A)log A)$。($A$ 为端点坐标最大值)

    代码细节,为了不让 $to[i][j]<i$,一开始把 $mx[i]$ 设成 $i$ 就行了,不影响答案。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=500050;
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
        char ch=getchar();ll x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,m,k=500000,mx[maxn],to[maxn][20];
    int main(){
        n=read();m=read();
        FOR(i,0,k) mx[i]=i;
        FOR(i,1,n){
            int l=read(),r=read();
            mx[l]=max(mx[l],r);
        }
        FOR(i,1,k) mx[i]=max(mx[i-1],mx[i]);
        FOR(i,0,k) to[i][0]=mx[i];
        FOR(j,1,19) FOR(i,0,k) to[i][j]=to[to[i][j-1]][j-1];
        while(m--){
            int x=read(),y=read(),cnt=0;
            ROF(i,19,0) if(to[x][i]<y) cnt+=1<<i,x=to[x][i];
            if(to[x][0]<y) puts("-1");
            else printf("%d
    ",cnt+1);
        }
    }
    View Code

    F,G

    还不会,以后再来搞。

  • 相关阅读:
    内置系统账户:Local system/Network service/Local Service 区别
    Asp.net生成工作流、审批流的解决方案(asp.net workflow svg)
    互联网创业盈利模式指南
    Web.config:OracleClient链接配置
    软件需求设计评审的八项要点需注意
    sscanf函数
    hdu1016Prime Ring Problem(经典DFS)
    hdu 1789 Doing Homework again (贪心)
    hdu1398 Square Coins(母函数、完全背包)
    C语言数字转化为字符串的库函数(转载)
  • 原文地址:https://www.cnblogs.com/1000Suns/p/10987043.html
Copyright © 2020-2023  润新知