zoukankan      html  css  js  c++  java
  • AGC007题解

    发现自己思维能力又跟不上了...做题有点吃力...所以回归AGC刷题计划...

    AGC040506都写了一部分题然后懒得补全了,所以从07开始做吧。大概是从C开始。

    C

    这也太人类智慧了吧...

    我先是自己画了个柿子 咱也不知道对不对 先丢着

    $frac{1}{i-j+1} * frac{1}{2^{j-n+1}} * ((2i-2j+1)d_1 + frac{2i+2j-3}{2i-2j+1} x)$

    就是根据每一个球到哪一个洞推的,发现是小数显然用不了 鸽了。

    然后就发现了这人类智慧的题解

    发现有个性质没用上 就是等差数列 我们接着转换问题

    变成数轴上有2n个点 每次可以取走相邻两颗 贡献是它俩之间的距离

    惊喜一刻到了:可以发现每次距离期望的变化是等差数列!

    等差数列+等差数列依然是等差数列= =

    所以我们直接维护首项末项和公差就可以计算了

    好像...很人类智慧...

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 20021225
    #define db double
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    int n,x,k;
    int main()
    {
        n=read(); x=read(); k=read();
        db bg=x,ed=x+(2.0*n-1)*k,ans=0.0;
        for(int i=(n<<1);i;i-=2)
        {
            ans+=(bg+ed)/2.0;
            bg+=(bg*2+k*5)/(1.0*i);
            ed+=(ed*2-k*5)/(1.0*i);
            if(i>2)    k=(ed-bg)/((i-2)*1.0-1.0);
        }
        printf("%.10lf
    ",ans);
        return 0;
    }
    C

    D

    这个题...比C简单多了啊...AGC的题目顺序真是个迷...

    写个柿子$f[i]=min(f[i],f[j]+max { T,2*p[i]-p[j+1] } )$

    显然有单调性...分类讨论一波max的取值维护一下就行了...

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define ll long long
    #define inf 20021225
    #define N 100100
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    ll f[N],mn; int t,e,n,p[N];
    int main()
    {
        n=read(),e=read(),t=read();
        int l=0; mn=1e18;
        for(int i=1;i<=n;i++)    p[i]=read();
        for(int i=1;i<=n;i++)
        {
            while(l<=i && 2*(p[i]-p[l+1])>t)
                mn=min(mn,f[l]-2*p[l+1]), l++;
            if(l<i)    f[i]=f[l]+t;
            f[i]=min(f[i],mn+2*p[i]);
        }
        printf("%lld
    ",f[n]+e);
        return 0;
    }
    D

    E

    神仙题.jpg

    发现答案具有二分性 然后考虑怎么验证

    我们用f[x][i][j]表示进x子树为i,出来是j是否可行。发现进去的方式至多只有leaf种,所以这玩意很多都没用,我们考虑把它们单拎出来。

    继续考虑如果存在(i,j)(i',j')且满足(i<=i'&&j<=j')的时候,只需要保留(i,j)这样的话我们把一个f[x]的数量级降到了O(n)

    考虑如何合并 我们需要对应的枚举(ls,i,j)(rs,k,l)使得(j+k+val[ls]+val[rs]<=mid)得到(x,i+val[ls],l+val[rs]) 由于上面的性质,当i单调增时,j单调降。所以我们直接双指针搞就可以了。

    考虑复杂度问题 用Sx表示f[x]的个数 我们发现 Sx=2*min(Sls,Srs)(翻转对应两种)使用启发式合并,我们的复杂度就可以降到O(nlgnlgw)了。

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #define ll long long
    #define inf 20021225
    #define pa pair<ll,ll>
    #define mp make_pair
    #define fs first
    #define se second
    #define N 131072
    #define pb push_back
    #define ls(x) son[x][0]
    #define rs(x) son[x][1]
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    vector<int> son[N+2]; int val[N+2];
    vector<pa> f[N+2],tmp[2]; ll mid;
    void dfs(int x)
    {
        f[x].clear();
        if(!son[x].size()){f[x].pb(mp(0,0)); return;}
        dfs(ls(x)); dfs(rs(x));
        for(int p=0;p<2;p++)
        {
            tmp[p].clear(); int a=son[x][p],b=son[x][p^1]; int r=0;
            for(int i=0;i<f[a].size();i++)
            {
                while(r+1<f[b].size()&&f[b][r+1].fs+f[a][i].se+val[a]+val[b]<=mid)    r++;
                if(r<f[b].size() && f[b][r].fs+f[a][i].se+val[a]+val[b]<=mid)    tmp[p].pb(mp(f[a][i].fs+val[a],f[b][r].se+val[b]));
            }
        }
        int i=0,j=0; ll cur=1e18;
        while(i<tmp[0].size()&&j<tmp[1].size())
        {
            if(tmp[0][i]<tmp[1][j])
            {
                if(tmp[0][i].se<cur)
                    f[x].pb(tmp[0][i]),cur=tmp[0][i].se;
                i++;
            }
            else
            {
                if(tmp[1][j].se<cur)
                    f[x].pb(tmp[1][j]),cur=tmp[1][j].se;
                j++;
            }
        }
        while(i<tmp[0].size())
        {
            if(tmp[0][i].se<cur)
                f[x].pb(tmp[0][i]),cur=tmp[0][i].se;
            i++;
        }
        while(j<tmp[1].size())
        {    
            if(tmp[1][j].se<cur)
                f[x].pb(tmp[1][j]),cur=tmp[1][j].se;
            j++;
        }
    }
    bool check()
    {
        dfs(1);
        if(f[1].size())    return 1;
        return 0;
    }
    int main()
    {
        int n=read(); ll l=0,r=0;
        for(int i=2;i<=n;i++)
        {
            int fa=read(); val[i]=read();
            son[fa].pb(i); r+=val[i];
        }
        ll ans=r;
        while(l<=r)
        {
            mid=l+r>>1;
            if(check())    ans=mid,r=mid-1;
            else    l=mid+1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    E
     

    F

    为什么他们什么都能想到啊QAQ

    建议去看editorial...

    大概就是维护拐点信息,感性理解还是可以的...大概自己做是没戏了...

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define ll long long
    #define inf 20021225
    #define N 1001000
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return f*s;
    }
    char s[N],t[N]; queue<int> q;
    int main()
    {
        int n=read(),ans=0;
        scanf("%s",s+1);
        scanf("%s",t+1);
        if(strcmp(s+1,t+1)==0)    return printf("0
    "),0;
        int pt=n,ps=n;
        while(pt)
        {
            while(pt && t[pt]==t[pt-1]) pt--;
            while(ps && (ps>pt||s[ps]!=t[pt]))    ps--;
            if(!ps)    return printf("-1
    "),0;
            while(!q.empty() && q.front()-q.size()>=pt)    q.pop();
            if(ps!=pt)    q.push(ps);
            ans=max(ans,(int)q.size()+1);
            pt--;
        }
        printf("%d
    ",ans);
        return 0;
    }
    F
  • 相关阅读:
    谈谈焦虑
    Bridge
    Abstract Factory
    开篇辞
    缓存穿透和缓存雪崩
    缓存与数据库的一致性思考
    GDB
    代码格式化
    CSMA/CA协议
    18年秋招(19届)复习指导+面经总结,手把手教你进大厂——阿里、网易、京东、多益等
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/11549936.html
Copyright © 2011-2022 走看看