Codeforces 1552 C. Maximize the Intersections —— 贪心,思维(双语)

51 篇文章 0 订阅

This way

题意:

现在有n*2个点围成一个圈,告诉你有m对点已经相连。让你自由让剩下n*2=m*2个点两两相连,每个点最多被用到一次。问你最后这些线段最多有多少交点(不用管点的间距)。

题解:

这种题目我还不太会做…
首先考虑n*2个点围成的圈,假设没有已经相连该怎么做最大。
一开始连一条边,然后连第二条边的时候与第一条有一个交点,连第三条的时候与前两条都有交点…以此类推。
那么我们就知道是前n个点一次跟后n个点相连,就像这样:
1连n,2连n+1,3连n+2…
但是现在有已经相连的情况。这个时候怎么连是最大的,也就是较短间隔的所有可使用的点连得边都与他有交点,或许是这样:
在这里插入图片描述
那么对于蓝色的已经固定的线来说,这样就是与它交点最大的一种情况。
那么我们可以发现,前面所描述的前n个点与后n个点依次相连的方法可以让较少的部分的所有可使用的点都与它有交点。那么最终答案就是如此。
计算交点的时候,正常来说如果数据范围是1e5,那么就需要使用树状数组这种数据结构维护差分数组来做,但是它只有100的数据范围,因此直接 n 2 n^2 n2来找答案即可。

C++代码:

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
const int N=205;
vector<pii>vec;
int vis[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        vec.clear();
        memset(vis,0,sizeof(vis));

        int n,m;
        scanf("%d%d",&n,&m);
        int ans=0;
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            vis[x]=vis[y]=1;
            vec.push_back({min(x,y),max(x,y)});
        }
        int res=n-m,sta=1;
        while(res){
            if(!vis[sta])res--;
            sta++;
        }
        for(int i=1;sta<=n*2;i++){
            if(vis[i])continue;
            while(vis[sta])sta++;
            if(sta>n*2)break;
            vec.push_back({i,sta});
            sta++;
        }
        for(int i=0;i<vec.size();i++){
            for(int j=i+1;j<vec.size();j++){
                int x1=vec[i].first,y1=vec[i].second,x2=vec[j].first,y2=vec[j].second;
                if(y1>y2)swap(x1,x2),swap(y1,y2);
                if(x2>x1&&x2<y1)ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

Python代码:

t=int(input())
while t>0:
    t=t-1
    n,m=map(int,input().split(' '))
    ans=0
    vec=[]
    vis=[0]*205
    for i in range(1,m+1):
        x,y=map(int,input().split(' '))
        vec.append([min(x,y),max(x,y)])
        vis[x]=vis[y]=1
    res=n-m;sta=1
    while res>0:
        if vis[sta]==0:
            res=res-1
        sta=sta+1
    for i in range(1,n*2+1):
        if vis[i]==1:continue
        while vis[sta]==1 :sta+=1
        if sta>n*2:break
        vec.append([i,sta])
        sta=sta+1
    l= len(vec)
    for i in range(l):
        for j in range(i+1,l):
            x1=vec[i][0];y1=vec[i][1];x2=vec[j][0];y2=vec[j][1]
            if y1>y2 :x1,x2=x2,x1;y1,y2=y2,y1
            if (x2>x1)and(x2<y1):ans=ans+1
    print(ans)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值