zoukankan      html  css  js  c++  java
  • Codeforces Round #310 (Div. 2)

    Problem A:

    题目大意:给你一个由0,1组成的字符串,如果有相邻的0和1要消去,问你最后还剩几个字符。

    写的时候不想看题意直接看样例,结果我以为是1在前0在后才行,交上去错了。。后来仔细

    看了看,哎。以后不能自以为是啊。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2*1e5+2;
    char s[N];
    bool vis[N];
    int main()
    {
        int n;
        scanf("%d%s",&n,s);
        int cnt=n;
        int cnt1=0,cnt0=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='0') cnt0++;
            else cnt1++;
        }
        printf("%d
    ",max(cnt0-cnt1,cnt1-cnt0));
    }
    View Code

    Problem B:

    题目大意:给你n个一排的齿轮,每个齿轮有编号(0->n-1)的锯齿,问你能不能转动第一个轮子,

    使其向上的锯齿依次为,0,1,2,3...n-1。水题,你就把第一个齿轮转到0的次数记录下来,第偶数

    个加上,奇数个减去,判断一下。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1005;
    int a[N];
    int main()
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        int cnt=n-a[0];
        //printf("%d
    ",cnt);
        for(int i=1;i<n;i++)
        {
            if(i%2)
            {
                if((a[i]-cnt+n)%n!=i)
                {
                    puts("No");
                    return 0;
                }
            }
            else
            {
                if((a[i]+cnt+n)%n!=i)
                {
                    puts("No");
                    return 0;
                }
            }
        }
        puts("Yes");
        return 0;
    }
    View Code

    Problem C:

    题目大意:给你n个编号1->n的杯子,编号代表了它们的大小,只有大的能套在小的上,现在

    给你这些杯子现在的情况,让你把他变成1<-2<-3<-4....<-n这种形式需要操作几次。简单模拟

    一下就好了。

    #include<bits/stdc++.h>
    using namespace std;
    int n,k,ans,st;
    int pre[100005];
    void Find(int x)
    {
        if(pre[x]!=x)
        {
            Find(pre[x]);
            ans++;
            pre[x]=x;
        }
    }
    void judge(int now,int p)
    {
        if(now==p+1 || p==-1)
        {
            st=now;
            judge(pre[now],now);
        }
    }
    int main()
    {
        cin>>n>>k;
        for(int i=1;i<=n;i++) pre[i]=i;
        for(int i=1;i<=k;i++)
        {
            int m;
            scanf("%d",&m);
            int p=-1;
            while(m--)
            {
                int g;
                scanf("%d",&g);
                if(p!=-1)
                {
                    pre[p]=g;
                }
                p=g;
            }
        }
        ans=0;
        st=1;
        judge(1,-1);
        Find(st);
        for(int i=st+1;i<=n;i++)
        {
            Find(i);
            pre[i-1]=i;
            ans++;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    Problem D:

    题目大意:有n个排成以行的小道他们的范围分别是(l[i]->r[i])且l[i+1]>r[i],现在有m个长度为b[i]的桥

    两个岛能加上长度为a的桥当且仅当 r[i+1]-l[i]>=a>=l[i+1]-r[i]。问你能不能完成这个工作。

    这个题很显然,可以转换成这个问题:有n-1个区间,m个数,每个数最多只能用一次,第i个数只

    要能被第j个区间包含,那么这个数就可以放入这个区间内。求出,当所有区间里都恰有一个数时的情况。

    我写的时候一直在想固定最大范围和最小范围来贪心,用桥去满足他们,这种方法是不对的。

    思路:我们可以将区间按按l排序,桥按长度排序,然后将当前满足 r>=a>=l 的区间都加到优先队列

    里面,每次取出r最小的区间,这个桥就搭在这个区间上,为什么呢,因为对于优先队列里面的区间

    来说,当前及以后的桥都满足,len[i]>=l 所以可以不用考虑区间的l,这样我们显然就可以贪心地取

    r小的区间。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=2*1e5+5;
    struct node
    {
        ll mx,mn;
        int id;
        bool operator <(const node&t) const
        {
            return mx>t.mx;
        }
    }w[N];
    bool cmp(node a,node b)
    {
        return a.mn<b.mn;
    }
    struct num
    {
        ll v;
        int id;
        bool operator <(const num &t)const
        {
            return v<t.v;
        }
    }a[N];
    ll ans[N];
    int n,m;
    int main()
    {
        cin>>n>>m;
        ll pl=-1,pr=-1;
        for(int i=0;i<n;i++)
        {
            ll l,r;
            scanf("%I64d%I64d",&l,&r);
            if(pl!=-1)
            {
                //printf("%d**
    ",i);
                w[i].mx=r-pl;
                w[i].mn=l-pr;
                w[i].id=i;
            }
            pl=l,pr=r;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%I64d",&a[i].v);
            a[i].id=i;
        }
        sort(a+1,a+1+m);
        sort(w+1,w+n,cmp);
        //for(int i=1;i<=m;i++) printf("%I64d ",a[i].v);
        //puts("");
        //for(int i=1;i<n;i++) printf("[%I64d,%I64d] ",w[i].mn,w[i].mx);
        priority_queue<node> Q;
        int cnt=0;
        for(int i=1,j=1;i<=m;i++)
        {
            while(w[j].mn<=a[i].v && a[i].v<=w[j].mx && j<n)
            {
                Q.push(w[j]);
                j++;
            }
            if(Q.empty()) continue;
            node now=Q.top();Q.pop();
            if(a[i].v>now.mx)
            {
                puts("No");
                return 0;
            }
            ans[now.id]=a[i].id;
            cnt++;
        }
        //printf("%d
    ",cnt);
        if(cnt<n-1)
        {
            puts("No");
            return 0;
        }
        puts("Yes");
        for(int i=1;i<n;i++) printf("%I64d%c",ans[i],i==n-1?'
    ' : ' ');
        return 0;
    }
    View Code

    problem E:

    题意:

    有一块n*n大小的巧克力,n<=1e9。现在进行操作,每次都从反对角线上选择一点,然后往上或往左一直吃,

    每当到达巧克力边缘或者下一块已经被吃了,则停止。问你每次操作能吃到几块巧克力。

    思维题,感觉挺难想到了,还是我太菜了。。

    思路:我们考虑从j列往上吃巧克力,吃掉的个数受什么影响呢,肯定不受<j的列印象,对它有直接影响的就

    他右边第一个有操作的点,如果这个点的操作时向左吃,则从j列向上吃只能吃到有操作点的那一行,如果右边

    第一个有操作的点是向上吃,则j列吃的和它一样。

    #include<bits/stdc++.h>
    using namespace std;
    map<int,int> u,l;
    int n,q;
    int main()
    {
        cin>>n>>q;
        while(q--)
        {
            int x,y;
            char s[3];
            scanf("%d%d%s",&x,&y,s);
            map<int,int>::iterator p;
            if(s[0]=='U')
            {
                int ans=0;
                p=u.lower_bound(x);
                if(u.count(x))
                {
                    puts("0");
                    continue;
                }
                if(p==u.end()) ans=y;
                else ans=y-(p->second);
                printf("%d
    ",ans);
                l[y]=x;
                u[x]=y-ans;
            }
            else
            {
                int ans=0;
                p=l.lower_bound(y);
                if(l.count(y))
                {
                    puts("0");
                    continue;
                }
                if(p==l.end()) ans=x;
                else ans=x-(p->second);
                printf("%d
    ",ans);
                u[x]=y;
                l[y]=x-ans;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    字符串 CSV解析 表格 逗号分隔值 通讯录 电话簿 MD
    Context Application 使用总结 MD
    RxJava RxPermissions 动态权限 简介 原理 案例 MD
    Luban 鲁班 图片压缩 MD
    FileProvider N 7.0 升级 安装APK 选择文件 拍照 临时权限 MD
    组件化 得到 DDComponent JIMU 模块 插件 MD
    gradlew 命令行 build 调试 构建错误 Manifest merger failed MD
    protobuf Protocol Buffers 简介 案例 MD
    ORM数据库框架 SQLite 常用数据库框架比较 MD
    [工具配置]requirejs 多页面,多入口js文件打包总结
  • 原文地址:https://www.cnblogs.com/CJLHY/p/7225837.html
Copyright © 2011-2022 走看看