• Codeforces Round #535 (Div. 3)


    A. Two distinct points

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=10010;
    const int inf=0x3f3f3f3f;
    int n,m;
    ll l1,r1,l2,r2;
    int main(){
        cin>>n;
        while(n--)
        {
            cin>>l1>>r1>>l2>>r2;
            if(l1!=l2)
            cout<<l1<<" "<<l2<<endl;
            else cout<<l1<<" "<<r2<<endl;
        }
    }
    View Code

    B. Divisors of Two Integers

    题意:给出x,y两个数的所有因子,如果一个因子同时存在于xy中,那么这个因子在数列中会出现两次,让你还原xy。

    首先最大的那个数肯定是x,然后统计每个数字出现次数,稍微想想就好了。

    水。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=10010;
    const int inf=0x3f3f3f3f;
    int n,m;
    ll a[maxn];
    int vis[10010];
    int main(){
        cin>>n;
        ll maxx=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            maxx=max(a[i],maxx);
            vis[a[i]]++;
        }
        printf("%lld ",maxx);
        ll x=1;
        for(int i=1;i<=10000;i++)
        {
            if(maxx%i==0){
                vis[i]--;
            }
        }
        for(int i=1;i<=10000;i++)
        {
            if(vis[i])
            maxx=i;
        }
        printf("%lld
    ",maxx);
    }
    View Code

    C. Nice Garland

    题意:给出一个灯的排列,使同样的灯间隔为3,并且rgb三个颜色要循环,求改变灯的最少次数。

    rgb总共有六种全排列,全列出来,暴力比较。

    比赛时看错题目 wa两发  代码还写的丑 我是弟弟。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=2*100010;
    const int inf=0x3f3f3f3f;
    int n,m;
    
    char s[maxn];
    string op="RGB";
    int main(){
        cin>>n;
        cin>>s+1;
        int ans=inf;
        int tep=0;
        int f=0;
        op="RGB";
        for(int i=1;i<=n;i++)
        {
            if(s[i]!=op[i%3]){
                tep++;
            }
        }
        if(tep<ans){
            f=1;
            ans=tep;
        }
        op="BRG";
        tep=0;
        for(int i=1;i<=n;i++)
        {
            if(s[i]!=op[i%3]){
                tep++;
            }
        }
        if(tep<ans){
            f=2;
            ans=tep;
        }
        op="GBR";
        tep=0;
        for(int i=1;i<=n;i++)
        {
            if(s[i]!=op[i%3]){
                tep++;
            }
        }
        if(tep<ans){
            f=3;
            ans=tep;
        }
        
        op="RBG";
        tep=0;
        for(int i=1;i<=n;i++)
        {
            if(s[i]!=op[i%3]){
                tep++;
            }
        }
        if(tep<ans){
            f=4;
            ans=tep;
        }    
        
        op="BGR";
        tep=0;
        for(int i=1;i<=n;i++)
        {
            if(s[i]!=op[i%3]){
                tep++;
            }
        }
        if(tep<ans){
            f=5;
            ans=tep;
        }    
        
        op="GRB";
        tep=0;
        for(int i=1;i<=n;i++)
        {
            if(s[i]!=op[i%3]){
                tep++;
            }
        }
        if(tep<ans){
            f=6;
            ans=tep;
        }    
        
    
        printf("%d
    ",ans);
        if(f==2){
            for(int i=1;i<=n;i++)
            {
                if(i%3==1)printf("R");
                if(i%3==2)printf("G");
                if(i%3==0)printf("B");
            }
        }
        if(f==3){
            for(int i=1;i<=n;i++)
            {
                if(i%3==1)printf("B");
                if(i%3==2)printf("R");
                if(i%3==0)printf("G");
            }
        }
        if(f==4){
            for(int i=1;i<=n;i++)
            {
                if(i%3==1)printf("B");
                if(i%3==2)printf("G");
                if(i%3==0)printf("R");
            }
        }
        if(f==5){
            for(int i=1;i<=n;i++)
            {
                if(i%3==1)printf("G");
                if(i%3==2)printf("R");
                if(i%3==0)printf("B");
            }
        }
        
        if(f==6){
            for(int i=1;i<=n;i++)
            {
                if(i%3==1)printf("R");
                if(i%3==2)printf("B");
                if(i%3==0)printf("G");
            }
        }
        if(f==1){
            for(int i=1;i<=n;i++)
            {
                if(i%3==1)printf("G");
                if(i%3==2)printf("B");
                if(i%3==0)printf("R");
            }
        }
        puts("");
        
    }
    View Code

    D. Diverse Garland

    题意:还是给出一个灯的排列,要使相邻的灯颜色不一样,求改变灯的最少次数。

    贪心的想,如果有两个相邻的灯,我肯定要改变其中一个,那么优先改变后面的肯定是最优的,因为我在改变第i+1个灯的时候,不但可以使其和 i 不一样,还能使其和i+2不一样。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=2*100010;
    const int inf=0x3f3f3f3f;
    int n,m;
    
    char s[maxn];
    char ans[maxn];
    string op="RGB";
    int main(){
        cin>>n;
        cin>>s+1;
        s[n+1]='c';
        int tot=0;
        ans[1]=s[1];
        for(int i=2;i<=n;i++)
        {
            if(s[i]==ans[i-1]){
                for(int j=0;j<3;j++)
                {
                    if(op[j]!=ans[i-1]&&op[j]!=s[i+1]){
                        ans[i]=op[j];
                        break;
                    }
                }
                tot++;
            }else{
                ans[i]=s[i];
            }
        }
        printf("%d
    ",tot);
        for(int i=1;i<=n;i++)
        {
            printf("%c",ans[i]);
        }
        puts("");
    }
    View Code

     (E1) Array and Segments (Easy version)

    题意:给出n个数字,这里n的范围是300,再给出m个区间,对于每个区间,你可以使下标在这个区间内所有数字都-1,也可以不操作。现在要求最优操作,使得操作过后最大值减最小值 最大,输出答案,并且输出选取了几个区间和哪些区间。

    这道题和hard版本差的只是数据范围,有一个思想是通用的,就是假设 第 i 个数字是最后的最小值,那么使所有覆盖了这个 i 的所有区间都生效后,答案一定是 在选取了 i 后最优的。为什么呢?由于 i 是最小值,假设 j 是最大值,如果 j 没有被 i 连累 ,那么差值肯定会变大(i变小了,j没变),如果被 i 连累了,那么两个同时缩小,对答案没影响。所以我们只要枚举所有的 i 使 所有包含了 i 区间生效就可以了。

    对于每一次枚举,在这个简单版本里,应该可以(没试过,时间复杂度是能结束的)暴力的把每一个区间都减去,然后比完最大值 - a[ i ]后,再把他还原。这样做的时间复杂度是o(n^3)。

    我用了01差分。时间复杂度优化到o(n^2).

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=310;
    const int inf=0x3f3f3f3f;
    int n,m;
    int a[maxn],b[maxn],l[maxn],r[maxn];
    int c[maxn];
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&l[i],&r[i]);
        }
        int ans=0,teo=1,tep=0;
        for(int i=1;i<=n;i++)
        {
            CLR(c,0);
            
            for(int j=1;j<=m;j++)
            {
                if(l[j]<=i&&r[j]>=i){
                    c[l[j]]--;
                    c[r[j]+1]++;
                }
            }
            int maxx=-inf;
            for(int j=1;j<=n;j++)
            {
                c[j]+=c[j-1];
                b[j]=a[j]+c[j];
                maxx=max(b[j],maxx);
            }
            if(maxx-b[i]>ans)
            {
                ans=maxx-b[i];
                teo=i;
            }
        }
        printf("%d
    ",ans);
        int tt[maxn];
        for(int i=1;i<=m;i++)
        {
            if(l[i]<=teo&&r[i]>=teo){
                tt[++tep]=i;
            }
        }
        printf("%d
    ",tep);
        for(int i=1;i<=tep;i++)
        {
            printf("%d",tt[i]);
            if(i<tep)printf(" ");
            else puts("");
        }
    }
    View Code

    E2. Array and Segments (Hard version)

    题意:和上题一样,n变成1e5.

    上题的时间复杂度不能被接受了,所以我们要考虑优化。

    看上一个版本,n的枚举显然是没法优化了,但是我们发现每次我们在对m个区间进行操作时浪费了很多的时间,所以我们在这里优化。

    如果一个区间已经覆盖了[4,5],那么在我们处理完4这个点的信息后,显然不需要还原,因为这个区间对5还是有用的,如果我们把一个区间在 l 这个位置加入,在 r 这个位置消除,那我们对每一个区间就只需要处理两次,然后我们用线段树来维护a[ n ]数组的最大值,并且用线段树完成  -1 +1的操作,就可以了。

    所以我们要先处理出这些区间是在哪个地方插入的,哪个地方删除的,所以还是用到差分的思想,每个 i 都开一个vector,然后对于标号为id 的区间 l r,往v[ l ]里塞入id, v[ r ]里塞入-id,正数代表我要加入某一个区间的影响,负数代表我要消除某一个区间的影响。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    const int inf=0x3f3f3f3f;
    ll a[maxn];
    struct node{
        ll ma,lazy;
    }tr[maxn<<2];
    vector<int > v[maxn];
    int l[maxn],r[maxn],n,m,tt[310];
    ll ans,teo,tep;
    void init(){
        ans=0,teo=0,tep=0;
        for(int i=1;i<=n;i++)
        {
            v[i].clear();
        }
    }
    void build(int o,int l,int r){
        if(l==r){
            tr[o].ma=a[l];
            tr[o].lazy=0;
            return ;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build((o<<1)|1,mid+1,r);
        tr[o].ma=max(tr[o<<1].ma,tr[(o<<1)|1].ma);
        tr[o].lazy=0;
    }
    void pushup(int o){
        tr[o].ma=max(tr[o<<1].ma,tr[o<<1|1].ma);
    }
    void pushdown(int o,int l,int r){
        if(tr[o].lazy){
            tr[o<<1].lazy+=tr[o].lazy;
            tr[o<<1|1].lazy+=tr[o].lazy;
            tr[o<<1].ma+=tr[o].lazy;
            tr[o<<1|1].ma+=tr[o].lazy;
            tr[o].lazy=0;
        }
    }
    void update(int o,int l,int r,int ql,int qr,ll val){
        if(ql<=l&&r<=qr){
            tr[o].lazy+=val;
            tr[o].ma+=val;
            return;
        }
        pushdown(o,l,r);
        int mid=l+((r-l)>>1);
        if(ql<=mid)update(o<<1,l,mid,ql,qr,val);
        if(qr>=mid+1)update(o<<1|1,mid+1,r,ql,qr,val);
        pushup(o);
    }
    ll query(int o,int l,int r,int ql,int qr){
        if(ql<=l&&qr>=r)return tr[o].ma;
        pushdown(o,l,r);
        int mid=(l+r)>>1;
        ll ans=-inf;
        if(ql<=mid)ans=query(o<<1,l,mid,ql,qr);
        if(qr>=mid+1)ans=max(ans,query(o<<1|1,mid+1,r,ql,qr));
        return ans;
    }
    int main(){
        while(cin>>n>>m)
        {
            init();
            build(1,1,n);
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);
            }
            build(1,1,n);
            for(int i=1;i<=m;i++)
            {
                scanf("%d %d",&l[i],&r[i]);
                v[l[i]].push_back(i);
                v[r[i]+1].push_back(-i);
            }
            for(int i=1;i<=n;i++)
            {
                int sz=v[i].size();
                for(int j=0;j<sz;j++)
                {
                    int x=v[i][j];
                    if(x>=0){
                        update(1,1,n,l[x],r[x],-1);
                    }else{
                        x=-x;
                        update(1,1,n,l[x],r[x],1);
                    }
                }
                
                ll maxx=query(1,1,n,1,n);
                ll b=query(1,1,n,i,i);
                
                if(maxx-b>ans){
                    ans=maxx-b;
                    teo=i;
                }
            }
            //printf("debug
    ");
            for(int i=1;i<=m;i++)
            {
                if(l[i]<=teo&&r[i]>=teo){
                    tt[++tep]=i;
                }
            }
            printf("%lld
    %lld
    ",ans,tep);
            for(int i=1;i<=tep;i++)
            {
                printf("%d%c",tt[i],(i<tep)?' ':'
    ');
            }
        }
    }
    View Code

    F. MST Unification

    题意:给出一幅图,这幅图可能有很多最小生成树,现在你可以操作若干次,每次操作可以任选一条边使其权值+1,一条边可以多次选择,使得最小生成树唯一,并且最小生成树的权值不变。

    首先克鲁斯卡尔跑一遍生成树,然后把有用边重新构图,变成一棵新的树,把所有无用边都标记一下,然后求边的两个端点和生成树形成的环的最大长度是不是等于自己,如果等于自己,则代表这条边可以取代这个最大长度,成为生成树的一部分。(环上不会有大于自己的边,否则就不会是最小生成树了)。求最大长度的方法是lca。

    求lca的时候,dfs千万不要把1号节点的父节点设成-1,否则会re,oj可能还不报re只报wa,kk要是再这样写,kk就把题目吃下去。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    struct edge{
        int u,v;
        ll w;
        friend bool operator <(const edge &a,const edge &b){
            return a.w<b.w;
        }
    };
    struct node{
        int to,Next;
        ll w;
    }te[maxn<<1];
    vector<edge>e;
    int n,m,tot,dep[maxn];
    int u,v,fa[maxn],head[maxn],f[maxn][30];
    ll w,ma[maxn][30];
    void addv(int u,int v,ll w){
        te[++tot].to=v;
        te[tot].w=w;
        te[tot].Next=head[u],head[u]=tot;
    }
    bool vis[maxn];
    void init(){
        tot=0;
        CLR(head,-1);
        CLR(vis,0);
        e.clear();
        for(int i=1;i<=n;i++)fa[i]=i;
    }
    int find(int x){
        return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    void dfs(int u,int fa,int deep,ll w){
        f[u][0]=fa,dep[u]=deep,ma[u][0]=w;
        for(int i=head[u];i != -1;i=te[i].Next){
            int v=te[i].to;
            if(v==fa)continue;
            dfs(v,u,deep+1,te[i].w);
        }
    }
    void work(){
        for(int j=1;j<=20;j++)
        {
            for(int i=1;i<=n;i++)
            {
                f[i][j]=f[f[i][j-1]][j-1];
                ma[i][j]=max(ma[i][j-1],ma[f[i][j-1]][j-1]);
            }
        }
    }
    ll lca(int p,int q){
        if(dep[p]<dep[q])swap(p,q);
        ll res=0;
        for(int i=20;i>=0;i--)
        {
            if(dep[f[p][i]]>=dep[q])
            {
                res=max(res,ma[p][i]);
                p=f[p][i];
            }
        }
        if(p==q)return res;
        for(int i=20;i>=0;i--)
        {
            if(f[p][i]!=f[q][i]){
                res=max(res,ma[p][i]);
                res=max(res,ma[q][i]);
                p=f[p][i],q=f[q][i];
            }
        }
        
        return max(res,max(ma[p][0],ma[q][0]));
    }
    int main(){
        while(cin>>n>>m)
        {
            init();
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%lld",&u,&v,&w);
                e.push_back({u,v,w});
            }
            sort(e.begin(),e.end());
            for(int i=0;i<m;i++)
            {
                u=e[i].u,v=e[i].v;
                w=e[i].w;
                int fx=find(u),fy=find(v);
                if(fx!=fy){
                    fa[fx]=fy;
                    addv(u,v,w);
                    addv(v,u,w);
                }else{
                    vis[i]=1;
                }
            }
            
            dfs(1,0,1,0);
            work();
            int ans=0;
            for(int i=0;i<m;i++)
            {
                if(vis[i]){
                    if(e[i].w==lca(e[i].u,e[i].v)){
                        ans++;
                    }
                }
            }
            printf("%d
    ",ans);
        }
    }
    View Code
  • 相关阅读:
    JSP XML数据处理
    JSP 连接数据库
    JSP 发送邮件
    IDEA新建maven项目没有webapp目录解决方法
    web项目中idea控制台中文乱码的解决方法
    Spring基础-12-基于xml配置的事务
    Spring基础-11-事务细节
    Spring基础-10-源码分析
    Spring基础-09-事务
    Spring基础-08-jdbcTemplate
  • 原文地址:https://www.cnblogs.com/mountaink/p/10315949.html
Copyright © 2020-2023  润新知