第十届山东省acm省赛补题(2)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4124

L Median

Time Limit: 1 Second      Memory Limit: 65536 KB

 

题意:一个序列有n个数,数值未知,给出m对大小关系,求对于每个数是否可以生成一个序列满足这个这个数为中位数,可以该位置输出1,反之输出0。

思路:考虑二元关系,可以建立有向图,考虑到数据范围很小,可以用floyed传递闭包,对于那些没有确定关系的数,他们的关系可以任意假设,所以只需要保证大(小)于他的元素个数少于n/2即可。感谢题目提供的特判提醒     另外进行特判时,必须在floyed传递闭包之后,因为这个wa了好几发。。。

代码如下:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int  maxn=105;
int a[maxn][maxn],ma[maxn],mi[maxn];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(a,0,sizeof(a));
        memset(ma,0,sizeof(ma));
        memset(mi,0,sizeof(mi));
        int n,m,flag=0;
        scanf("%d %d",&n,&m);
        for (int i=1; i<=m; i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            if (u==v)  flag=1;
            a[u][v]=1;
        }
        for (int k=1; k<=n; k++)
        {
            for (int i=1; i<=n; i++)
            {
                for (int j=1; j<=n; j++)
                {
                    a[i][j]=a[i][j]||(a[i][k]&&a[k][j]);
                }
            }
        }
        for (int i=1; i<=n; i++)
        {
            for (int j=1; j<=n; j++)
            {
                if (a[i][j]&&a[j][i])
                {
                    flag=1;
                    break;
                }
            }
            if (flag) break;
        }
        if (flag)
        {
            for (int i=1; i<=n; i++)
                putchar(48);
            putchar(10);
            continue ;
        }
        for (int i=1; i<=n;i++)
        {
            for (int j=1; j<=n; j++)
            {
                if (a[i][j])
                    ma[i]++,mi[j]++;
            }
        }
        for (int i=1; i<=n; i++)
        {
            if (ma[i]<=n/2 && mi[i]<=n/2)
                putchar(49);
            else putchar(48);
        }
        putchar(10);
    }
    return 0;
}
View Code

 

 5.17 补充 翻看ppt时,发现传递闭包那个题还可以bitset优化 改成    a[i][j]|=(a[i][k]&&a[k][j]);

优化后50ms-》30ms

F Tokens on the Segments

Time Limit: 1 Second      Memory Limit: 65536 KB

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4120

题意:给出n个线段(包括长度为0的点线段),这些线段都是平行于x轴的,对于每个x坐标只可以放一个硬币到任意线段上,求最多可以让几个线段放上硬币。

思路:

大致就是贪心+优先队列。

贪心思想就是,对于越短的线段越难放,所以同一个x坐标对应有多条线段时,尽量选短的,然后从x最小的开始放吧。

代买如下:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef struct node
{
    int s,e;
    bool friend operator < (node a,node b)
    {
        if (a.s!=b.s)
            return a.s>b.s;
        return a.e>b.e;
    }
}node;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        priority_queue <node> Q;
        int n,ma=-1,ans=0;
        scanf("%d",&n);
        for (int i=1; i<=n; i++)
        {
            node a;
            scanf("%d%d",&a.s,&a.e);
            Q.push(a);
        }
        while(!Q.empty())
        {
            node cur=Q.top();
            Q.pop();
            if (cur.s<=ma && cur.s+1<=cur.e)
            {
                node t=cur;
                t.s++;
                Q.push(t);
                continue ;
            }
            if (cur.s>ma)
            {
                ans++;
                ma=max(ma,cur.s);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2019-05-15 23:47  Fos、伤感  阅读(207)  评论(0编辑  收藏  举报