• Educational Codeforces Round 92 (Rated for Div. 2)


    A

    签到

    B

    直接DP,f[i][j]表示前i步j步向左的最大值,位置可以直接计算

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+7;
    int n,k,z,ans,a[N],f[N][6];
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&k,&z);
            for(int i=1;i<=n;i++)for(int j=0;j<=z;j++)f[i][j]=0;
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            f[0][0]=a[1];
            for(int i=1;i<=k;i++)
            for(int j=0;j<=min(i-1,z);j++)
            {
                int pos=i-2*j;
                if(pos>1&&j<z)f[i][j+1]=max(f[i][j+1],f[i-1][j]+a[pos-1]);
                if(pos<n)f[i][j]=max(f[i][j],f[i-1][j]+a[pos+1]);
            }
            ans=0;
            for(int i=0;i<=z;i++)ans=max(ans,f[k][i]);
            printf("%d
    ",ans);
        }
    }
    View Code

    C

    求最少删除次数等价于求最长序列。容易发现,最长序列有两种情况:1、全为字符a;2、长度为偶数,ababab交替。方案1记录数量最多的数字,方案2枚举ab扫描一遍即可,复杂度O(81Σn)

    #include<bits/stdc++.h>
    using namespace std;
    int n,ans;
    char s[200050];
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            scanf("%s",s+1);
            n=strlen(s+1);
            int num;
            ans=0;
            for(int i='0';i<='9';i++)
            {
                num=0;
                for(int j=1;j<=n;j++)if(s[j]==i)num++;
                ans=max(ans,num);
            }
            for(int a='0';a<='9';a++)
            for(int b='0';b<='9';b++)
            if(a!=b)
            {
                int now=a,num=0;
                for(int i=1;i<=n;i++)if(s[i]==now)
                {
                    num++;
                    now=now==a?b:a;
                }
                if(num%2)num--;
                ans=max(ans,num);
            }
            printf("%d
    ",n-ans);
        }
    }
    View Code

    D

    对于两条线段,不妨三种情况:1、完全包含;2、部分包含;3、无交集。前两种直接计算,尽量改变重叠部分。第三种可以枚举改变i组线段,然后转化为第二种方案。时间复杂度O(Tn)(不然T,n给你那么小干嘛?)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int T;
    ll n,k,l1,r1,l2,r2,ans;
    int main()
    {
        cin>>T;
        while(T--)
        {
            cin>>n>>k>>l1>>r1>>l2>>r2;
            if(l1>l2||l1==l2&&r1<r2)swap(l1,l2),swap(r1,r2);
            if(r1>=r2)
            {
                ll rst=(r1-l1)-(r2-l2);
                if(k<=(r2-l2)*n)puts("0");
                else if(k<=(r1-l1)*n)printf("%lld
    ",k-(r2-l2)*n);
                else printf("%lld
    ",rst*n+(k-(r1-l1)*n)*2);
            }
            else if(r1>=l2)
            {
                ll rst=(r2-l1)-(r1-l2);
                if(k<=(r1-l2)*n)puts("0");
                else if(k<=(r2-l1)*n)printf("%lld
    ",k-(r1-l2)*n);
                else printf("%lld
    ",rst*n+(k-(r2-l1)*n)*2);
            }
            else{
                ans=9e18;
                for(int i=1;i<=n;i++)
                {
                    ll sum=i*(l2-r1);
                    if(k<=(r2-l1)*i)sum+=k;
                    else sum+=(r2-l1)*i+(k-(r2-l1)*i)*2;
                    ans=min(ans,sum);
                }
                printf("%lld
    ",ans);
            }
        }
    }
    View Code

    E

    老年选手不会用脑子了!若a月b日和b月a日如果是一周的同一天,则(b-1)*d+a-( (a-1)*d+b)被w整除,化简得(b-a)(d-1)%w==0,设c=b-a,则c*(d-1)%w==0。若(d-1)%w=0,则c为任意正整数 ,ans=md*(md-1)/2,md=min(m,d)。若(d-1)%w!=0,那c是lcm(w,(d-1)%w)/(d-1)%w的整数倍

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            int m,d,w,g;scanf("%d%d%d",&m,&d,&w);
            g=__gcd(w,d-1),w/=g,m=min(m,d);
            long long y=m/w;
            printf("%lld
    ",y*m-y*(y+1)/2*w);
        }
    }
    View Code

    F

    蒟蒻早知道看这题了,这题没有啥思维难度。根据颜色不同用2棵线段树维护DP即可。

    #include<bits/stdc++.h>
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define rot 0,tot,1
    using namespace std;
    const int N=4e5+7;
    struct ST{
        int mx[N<<2],lazy[N<<2];
        void addtag(int rt,int v){}
        void pushdown(int rt)
        {if(lazy[rt])mx[rt<<1]+=lazy[rt],lazy[rt<<1]+=lazy[rt],mx[rt<<1|1]+=lazy[rt],lazy[rt<<1|1]+=lazy[rt],lazy[rt]=0;}
        void update(int k,int v,int l,int r,int rt)
        {
            if(l==r){mx[rt]=max(mx[rt],v);return;}
            pushdown(rt);
            int m=l+r>>1;
            if(k<=m)update(k,v,lson);else update(k,v,rson);
            mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
        }
        void add(int L,int R,int v,int l,int r,int rt)
        {
            if(L<=l&&r<=R){mx[rt]+=v,lazy[rt]+=v;return;}
            pushdown(rt);
            int m=l+r>>1;
            if(L<=m)add(L,R,v,lson);
            if(R>m)add(L,R,v,rson);
            mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
        }
        int query(int L,int R,int l,int r,int rt)
        {
            if(L<=l&&r<=R)return mx[rt];
            pushdown(rt);
            int m=l+r>>1,ret=0;
            if(L<=m)ret=max(ret,query(L,R,lson));
            if(R>m)ret=max(ret,query(L,R,rson));
            return ret;
        }
    }tr[2];
    struct node{int l,r,t;}a[N];
    int n,tot,b[N];
    bool cmp(node a,node b){return a.l<b.l;}
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].t),a[i].t--,b[++tot]=a[i].l,b[++tot]=a[i].r;
        sort(b+1,b+tot+1);
        tot=unique(b+1,b+tot+1)-b-1;
        for(int i=1;i<=n;i++)
        a[i].l=lower_bound(b+1,b+tot+1,a[i].l)-b,a[i].r=lower_bound(b+1,b+tot+1,a[i].r)-b;
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            tr[a[i].t].update(a[i].r,max(tr[a[i].t^1].query(0,a[i].l-1,rot),tr[a[i].t].query(0,a[i].r,rot))+1,rot);
            if(a[i].r<tot)tr[a[i].t].add(a[i].r+1,tot,1,rot);
        }
        printf("%d",max(tr[0].query(0,tot,rot),tr[1].query(0,tot,rot)));
    }
    View Code

    G

    综合性很强的一题。先点双缩点,变成一个个强连通分量,然后以关键点为根,将树视为有根树,进行树上换根DP即可。

    #include<bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    const int N=3e5+7;
    struct edge{int u,v,w;}e[N];
    int n,m,cnt,rt,tot,tp,fa[N],low[N],dfn[N],st[N],bel[N],c[N],sz[N];
    bool sp[N],is[N];
    ll a[N],b[N],f[N],ans[N];
    vector<pair<int,int> > T[N];
    vector<int>G[N];
    void tarjan(int u,int f)
    {
        low[u]=dfn[u]=++tot,st[++tp]=u;
        for(int v:G[u])
        if(v!=f)
        {
            if(!dfn[v])tarjan(v,u),low[u]=min(low[u], low[v]);
            else low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            ++cnt;int v=0;
            while(u!=v)a[bel[v=st[tp--]]=cnt]+=c[v],is[cnt]|=sp[v];
        }
    }
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void dfs1(int u, int f)
    {
        sz[u]=is[u],b[u]=a[u];
        for(auto e:T[u])
        if(e.first!=f)
        {
            dfs1(e.first,u),sz[u]+=sz[e.first];
            if(!sz[e.first])fa[e.first]=u,b[u]+=b[e.first];
        }
    }
    void dfs2(int u,int fa)
    {
        f[u]=b[u];
        for(auto e:T[u])
        if(e.first!=fa&&sz[e.first])
        {
            dfs2(e.first, u);
            if(f[e.first]>e.second)f[u]+=f[e.first]-e.second;
        }
    }
    void dfs3(int u,int fa)
    {
        ans[u]=f[u];
        for(auto e:T[u])
        if(e.first!=fa&&sz[e.first])
        {
            f[u]-=max(0ll,f[e.first]-e.second);
            f[e.first]+=max(0ll,f[u]-e.second);
            dfs3(e.first,u);
            f[e.first]-=max(0ll,f[u]-e.second);
            f[u]+=max(0ll,f[e.first]-e.second);
        }
    }
    int main()
    {
        int k,x;scanf("%d%d%d",&n,&m,&k);
        while(k--)scanf("%d",&x),sp[x]=1;
        for(int i=1;i<=n;++i)scanf("%d",&c[i]);
        for(int i=1;i<=m;++i)scanf("%d",&e[i].w);
        for(int i=1;i<=m;++i)
        scanf("%d%d",&e[i].u,&e[i].v),G[e[i].u].pb(e[i].v),G[e[i].v].pb(e[i].u);
        tarjan(1,0);
        for(int i=1;i<=m;++i)
        {
            int u=bel[e[i].u],v=bel[e[i].v];
            if(u!=v)T[u].pb(make_pair(v,e[i].w)),T[v].pb(make_pair(u,e[i].w));
        }
        rt=0;
        for(int i=1;i<=cnt;++i)if(is[i])rt=i;
        for(int i=1;i<=cnt;++i)fa[i]=i;
        dfs1(rt,0),dfs2(rt,0),dfs3(rt,0);
        for(int i=1;i<=n;++i)printf("%lld ",ans[find(bel[i])]);
    }
    View Code

    rank=216 rating+=222

    新号卡线上紫啦!

  • 相关阅读:
    Pro Andorid3第二章:设置开发环境
    Seminar 记录
    安装CGAL
    Literature review
    第七章:清楚简洁的英文 《英语科技写作(文法与修辞原则)》by 方克涛
    幻灯片制作去除模板背景
    vs2008下设置.h, .lib和 .dll 的路径配置全图及其意义
    配置环境变量
    PPT制作技巧
    #include文件时用双引号和尖括号的区别
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/13401960.html
Copyright © 2020-2023  润新知