【codeforces #310】div1 A -- C

原创 2015年07月06日 20:33:01

A题:

题意:给你n个数以k组的形式排列,每组数内保证递增。每次操作可以取出一个数或者把一个数放在一列的最后,问最少经过多少次操作可以使得1--n排列在一列。

分析:首先可以假设若所有数都要先取下,再放到某一列,则要进行2 * n - k - 1次操作。

然后因为若1--i直接在一起,那么可以减少(i - 1)*2次操作,故可得代码。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,k,num,t;
    scanf("%d%d",&n,&k);
    int res = 2 * n - k - 1;
    for(int i = 0 ; i < k ; i ++){
        scanf("%d",&num);
        scanf("%d",&t);
        if(t != 1) for(int j = 1 ; j < num ; j ++) scanf("%d",&t);
        else{
            int flag = 1;
            for(int j = 1 ; j < num ; j ++){
                scanf("%d",&t);
                if(flag && t == j + 1) res -= 2;
                else flag = 0;
            }
        }
    }
    printf("%d\n",res);
    return 0;
}

B题:

题意:给你n个排在一列的岛屿,再给你m个桥,对于任意的i < n,可以在i到i+1之间放置一个大于等于岛中间距离小于等于岛两端距离的桥。问可否有一种方案,使所有相邻岛中间都有一座桥。

分析:对于相邻两岛之间,我们可以得到一个Max[i]和Min[i]分别代表i,i+1两岛之间最大和最小桥的长度。可以先将需求与桥以最小长度排序,对于每个桥,我们可以先将最小值小于等于桥的需求放到一个set里面,然后再set里面取一个最大值最小的,将此桥给它。这必定是最优方案。代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200005;
LL a[N],l[N],r[N];
struct elem{
    LL Max,Min;
    int id;
    void add(LL l1,LL r1,LL l2,LL r2,int _id){
        Max = r2 - l1;
        Min = l2 - r1;
        id = _id;
    }
    bool operator < (const elem &a)const{
        if(Min != a.Min) return Min < a.Min;
        return Max < a.Max;
    }
}ss[N];
struct brige{
    LL val;
    int id;
    bool operator < (const brige &a)const{
        return val < a.val;
    }
    void add(LL _val,int _id){
        val = _val;
        id = _id;
    }
}bb[N];
struct Node{
    LL val;
    int id;
    Node(LL _val = 0,int _id = 0):val(_val),id(_id){}
    bool operator < (const Node &a)const{
        return val > a.val;
    }
};
priority_queue<Node> Q;
int res[N];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i < n ; i ++) scanf("%I64d%I64d",&l[i],&r[i]);
    for(int i = 0 ; i < m ; i ++) scanf("%I64d",&a[i]);
    if(m < n - 1){
        printf("No\n");
        return 0;
    }
    for(int i = 0 ; i < n - 1 ; i ++)
        ss[i].add(l[i],r[i],l[i + 1],r[i + 1],i);
    for(int i = 0 ; i < m ; i ++)
        bb[i].add(a[i],i + 1);
    while(!Q.empty()) Q.pop();
    sort(ss,ss + n - 1);
    sort(bb,bb + m);
    int j = 0;
    for(int i = 0 ; i < m ; i ++){
        while(ss[j].Min <= bb[i].val && j < n - 1){
            Q.push(Node(ss[j].Max,ss[j].id));
            j ++;
        }
        while(!Q.empty() && Q.top().val < bb[i].val) Q.pop();
        if(Q.empty()) continue;
        Node u = Q.top();Q.pop();
        res[ u.id ] = bb[i].id;
    }
    int flag = 1;
    for(int i = 0 ; i < n - 1 ; i ++)
        if(res[i] == 0) flag = 0;
    if(flag == 0) printf("No\n");
    else{
        printf("Yes\n");
        for(int i = 0 ; i < n - 1 ; i ++) printf("%d ",res[i]);
        printf("\n");
    }
    return 0;
}

C题:

题意:对于块只有上三角的巧克力,每次从反对角线上开始吃,可以选择向上吃或者向左吃直到遇到空隙。给你一系列操作,问最多可以吃到多少格巧克力。

分析:首先可以考虑到使用线段树维护每一列最多能到那一行和维护每一行最多能到那一列。对于每个询问向上吃的操作,我们可以利用线段树的单点询问,找到能吃到那一行,然后对于吃到的这些块,再对向左吃的那一颗线段树进行update。对于向左吃的操作也可以这样。反复如此统计结果就好了。

还有一种更加巧妙的方法,对于向上吃的方法,可以找到离它最近的一个之前出现过的向上吃的位置记为l1,在找到一个距离它最近的标号比它大的向左吃的操作r1。若r1操作在l1的下方,那么l1不会影响到r1,则吃到r1为止。若r1,在l1的上方,则l1会拦住它或者在拦住l1的操作的上方,故为拦住l1的操作也是拦住此操作的操作。这样就可以知道此次操作吃到了多少块。对于向左吃的方法也是如此。

具体看代码:

选段树版本:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200005;
LL a[N],l[N],r[N];
struct elem{
    LL Max,Min;
    int id;
    void add(LL l1,LL r1,LL l2,LL r2,int _id){
        Max = r2 - l1;
        Min = l2 - r1;
        id = _id;
    }
    bool operator < (const elem &a)const{
        if(Min != a.Min) return Min < a.Min;
        return Max < a.Max;
    }
}ss[N];
struct brige{
    LL val;
    int id;
    bool operator < (const brige &a)const{
        return val < a.val;
    }
    void add(LL _val,int _id){
        val = _val;
        id = _id;
    }
}bb[N];
struct Node{
    LL val;
    int id;
    Node(LL _val = 0,int _id = 0):val(_val),id(_id){}
    bool operator < (const Node &a)const{
        return val > a.val;
    }
};
priority_queue<Node> Q;
int res[N];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i < n ; i ++) scanf("%I64d%I64d",&l[i],&r[i]);
    for(int i = 0 ; i < m ; i ++) scanf("%I64d",&a[i]);
    if(m < n - 1){
        printf("No\n");
        return 0;
    }
    for(int i = 0 ; i < n - 1 ; i ++)
        ss[i].add(l[i],r[i],l[i + 1],r[i + 1],i);
    for(int i = 0 ; i < m ; i ++)
        bb[i].add(a[i],i + 1);
    while(!Q.empty()) Q.pop();
    sort(ss,ss + n - 1);
    sort(bb,bb + m);
    int j = 0;
    for(int i = 0 ; i < m ; i ++){
        while(ss[j].Min <= bb[i].val && j < n - 1){
            Q.push(Node(ss[j].Max,ss[j].id));
            j ++;
        }
        while(!Q.empty() && Q.top().val < bb[i].val) Q.pop();
        if(Q.empty()) continue;
        Node u = Q.top();Q.pop();
        res[ u.id ] = bb[i].id;
    }
    int flag = 1;
    for(int i = 0 ; i < n - 1 ; i ++)
        if(res[i] == 0) flag = 0;
    if(flag == 0) printf("No\n");
    else{
        printf("Yes\n");
        for(int i = 0 ; i < n - 1 ; i ++) printf("%d ",res[i]);
        printf("\n");
    }
    return 0;
}

set版本:

#include<bits/stdc++.h>
using namespace std;
struct Node{
    int l,lim;
    Node(int l,int lim):l(l),lim(lim){}
    bool operator < (const Node &a)const{
        return l < a.l;
    }
};
set<Node> us,ls;
int main()
{
    char s[10];
    int n,q;
    int x,y;
    us.clear();ls.clear();
    scanf("%d%d",&n,&q);
    us.insert(Node(n + 1,0));
    us.insert(Node(0,0));
    ls.insert(Node(n + 1,0));
    ls.insert(Node(0,0));
    for(int i = 0 ; i < q ; i ++){
        scanf("%d%d%s",&x,&y,s);
        int flag = 0;
        auto It = us.lower_bound(Node(x,0));
        if(It->l == x) flag = 1;
        It = ls.lower_bound(Node(y,0));
        if(It->l == y) flag = 1;
        if(flag){
            printf("0\n");
            continue;
        }
        if(s[0] == 'U'){
            auto It1 = us.lower_bound(Node(x,0));
            auto It2 = ls.lower_bound(Node(y,0));
            It2--;
            if(It2->l > n + 1 - It1->l){
                printf("%d\n",y - It2->l);
                us.insert(Node(x,It2->l));
            }
            else{
                printf("%d\n",y - It1->lim);
                us.insert(Node(x,It1->lim));
            }
        }
        else{
            auto It1 = ls.lower_bound(Node(y,0));
            auto It2 = us.lower_bound(Node(x,0));
            It2 --;
            if(It2->l > n + 1 - It1->l){
                printf("%d\n",x - It2->l);
                ls.insert(Node(y,It2->l));
            }
            else{
                printf("%d\n",x - It1->lim);
                ls.insert(Node(y,It1->lim));
            }
        }
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Codeforces Round #310 (Div. 1) A B C D题

本题解包含题目: 555A Case of Matryoshkas 555B Case of Fugitive ...

Codeforces #310 div2 C. Case of Matryoshkas

C. Case of Matryoshkastime limit per test2 seconds memory limit per test256 megabytes inputstandar...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

Codeforces Round #310 (Div. 1) 完整题解

A题:看懂题意后,只要找到从1开始连续的长度就行了,其他的套娃都要全拆开。 #include #include #include #include #include #includ...

Codeforces Round #310 (Div. 2)-A. Case of the Zeros and Ones

ACM codeforces

Codeforces Round #310 (Div. 2) B. Case of Fake Numbers

time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandar...

[Codeforces Round #310 (Div. 2)] #ABC题解

没想到时隔两天竟然又打了cf,做了3题就弃疗了。题目链接:Codeforces Round #309 (Div. 2)A. Case of Zeros and Ones [Description] ...

Codeforces Round #310 (Div. 2)

看来最近身体状况并不是很好啊。。。 最近竟然有一次熬夜,然后心脏开始难受了,我可不想有心脏病啊,劳资还要上分呢。。。 ==b 首先是第一题,手速慢了一些,脑子也慢了些,然后回过神来,woc,1600个...

【Codeforces Round 345 (Div 1) C】【并查集缩环+拓扑最长路】Table Compression nm矩形权值缩小大小关系不变

C. Watchmen time limit per test 3 seconds memory limit per test 256 megabytes input...

Codeforces Round #302 (Div. 1) C

Remembering Strings         状压dp。本弱在被提示了姿势的情况下,依然想不到状压行还是列,以及如何转移。。。实在太弱了。         看了下题解,想明白了。dp...

Codeforces Round #371 (Div. 1) C. Sonya and Problem Wihtout a Legend

Codeforces Round #371 (Div. 1) C. Sonya and Problem Wihtout a Legend Sonya was unable to think ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)